summaryrefslogtreecommitdiffstats
path: root/doc/extsearch_flow.eps
blob: ed140cb22cde73f546b44209bb91c882ba7bc5d0 (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
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
%!PS-Adobe-3.0 EPSF-3.0
%Produced by poppler pdftops version: 0.18.4 (http://poppler.freedesktop.org)
%%Creator: cairo 1.10.2 (http://cairographics.org)
%%LanguageLevel: 2
%%DocumentSuppliedResources: (atend)
%%BoundingBox: 0 0 176 542
%%DocumentSuppliedResources: (atend)
%%EndComments
%%BeginProlog
%%BeginResource: procset xpdf 3.00 0
%%Copyright: Copyright 1996-2004 Glyph & Cog, LLC
/xpdf 75 dict def xpdf begin
% PDF special state
/pdfDictSize 15 def
/pdfSetup {
  3 1 roll 2 array astore
  /setpagedevice where {
    pop 3 dict begin
      /PageSize exch def
      /ImagingBBox null def
      /Policies 1 dict dup begin /PageSize 3 def end def
      { /Duplex true def } if
    currentdict end setpagedevice
  } {
    pop pop
  } ifelse
} def
/pdfStartPage {
  pdfDictSize dict begin
  /pdfFillCS [] def
  /pdfFillXform {} def
  /pdfStrokeCS [] def
  /pdfStrokeXform {} def
  /pdfFill [0] def
  /pdfStroke [0] def
  /pdfFillOP false def
  /pdfStrokeOP false def
  /pdfLastFill false def
  /pdfLastStroke false def
  /pdfTextMat [1 0 0 1 0 0] def
  /pdfFontSize 0 def
  /pdfCharSpacing 0 def
  /pdfTextRender 0 def
  /pdfPatternCS false def
  /pdfTextRise 0 def
  /pdfWordSpacing 0 def
  /pdfHorizScaling 1 def
  /pdfTextClipPath [] def
} def
/pdfEndPage { end } def
% PDF color state
/cs { /pdfFillXform exch def dup /pdfFillCS exch def
      setcolorspace } def
/CS { /pdfStrokeXform exch def dup /pdfStrokeCS exch def
      setcolorspace } def
/sc { pdfLastFill not { pdfFillCS setcolorspace } if
      dup /pdfFill exch def aload pop pdfFillXform setcolor
     /pdfLastFill true def /pdfLastStroke false def } def
/SC { pdfLastStroke not { pdfStrokeCS setcolorspace } if
      dup /pdfStroke exch def aload pop pdfStrokeXform setcolor
     /pdfLastStroke true def /pdfLastFill false def } def
/op { /pdfFillOP exch def
      pdfLastFill { pdfFillOP setoverprint } if } def
/OP { /pdfStrokeOP exch def
      pdfLastStroke { pdfStrokeOP setoverprint } if } def
/fCol {
  pdfLastFill not {
    pdfFillCS setcolorspace
    pdfFill aload pop pdfFillXform setcolor
    pdfFillOP setoverprint
    /pdfLastFill true def /pdfLastStroke false def
  } if
} def
/sCol {
  pdfLastStroke not {
    pdfStrokeCS setcolorspace
    pdfStroke aload pop pdfStrokeXform setcolor
    pdfStrokeOP setoverprint
    /pdfLastStroke true def /pdfLastFill false def
  } if
} def
% build a font
/pdfMakeFont {
  4 3 roll findfont
  4 2 roll matrix scale makefont
  dup length dict begin
    { 1 index /FID ne { def } { pop pop } ifelse } forall
    /Encoding exch def
    currentdict
  end
  definefont pop
} def
/pdfMakeFont16 {
  exch findfont
  dup length dict begin
    { 1 index /FID ne { def } { pop pop } ifelse } forall
    /WMode exch def
    currentdict
  end
  definefont pop
} def
% graphics state operators
/q { gsave pdfDictSize dict begin } def
/Q {
  end grestore
  /pdfLastFill where {
    pop
    pdfLastFill {
      pdfFillOP setoverprint
    } {
      pdfStrokeOP setoverprint
    } ifelse
  } if
} def
/cm { concat } def
/d { setdash } def
/i { setflat } def
/j { setlinejoin } def
/J { setlinecap } def
/M { setmiterlimit } def
/w { setlinewidth } def
% path segment operators
/m { moveto } def
/l { lineto } def
/c { curveto } def
/re { 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto
      neg 0 rlineto closepath } def
/h { closepath } def
% path painting operators
/S { sCol stroke } def
/Sf { fCol stroke } def
/f { fCol fill } def
/f* { fCol eofill } def
% clipping operators
/W { clip newpath } def
/W* { eoclip newpath } def
/Ws { strokepath clip newpath } def
% text state operators
/Tc { /pdfCharSpacing exch def } def
/Tf { dup /pdfFontSize exch def
      dup pdfHorizScaling mul exch matrix scale
      pdfTextMat matrix concatmatrix dup 4 0 put dup 5 0 put
      exch findfont exch makefont setfont } def
/Tr { /pdfTextRender exch def } def
/Tp { /pdfPatternCS exch def } def
/Ts { /pdfTextRise exch def } def
/Tw { /pdfWordSpacing exch def } def
/Tz { /pdfHorizScaling exch def } def
% text positioning operators
/Td { pdfTextMat transform moveto } def
/Tm { /pdfTextMat exch def } def
% text string operators
/cshow where {
  pop
  /cshow2 {
    dup {
      pop pop
      1 string dup 0 3 index put 3 index exec
    } exch cshow
    pop pop
  } def
}{
  /cshow2 {
    currentfont /FontType get 0 eq {
      0 2 2 index length 1 sub {
        2 copy get exch 1 add 2 index exch get
        2 copy exch 256 mul add
        2 string dup 0 6 5 roll put dup 1 5 4 roll put
        3 index exec
      } for
    } {
      dup {
        1 string dup 0 3 index put 3 index exec
      } forall
    } ifelse
    pop pop
  } def
} ifelse
/awcp {
  exch {
    false charpath
    5 index 5 index rmoveto
    6 index eq { 7 index 7 index rmoveto } if
  } exch cshow2
  6 {pop} repeat
} def
/Tj {
  fCol
  1 index stringwidth pdfTextMat idtransform pop
  sub 1 index length dup 0 ne { div } { pop pop 0 } ifelse
  pdfWordSpacing pdfHorizScaling mul 0 pdfTextMat dtransform 32
  4 3 roll pdfCharSpacing pdfHorizScaling mul add 0
  pdfTextMat dtransform
  6 5 roll Tj1
} def
/Tj16 {
  fCol
  2 index stringwidth pdfTextMat idtransform pop
  sub exch div
  pdfWordSpacing pdfHorizScaling mul 0 pdfTextMat dtransform 32
  4 3 roll pdfCharSpacing pdfHorizScaling mul add 0
  pdfTextMat dtransform
  6 5 roll Tj1
} def
/Tj16V {
  fCol
  2 index stringwidth pdfTextMat idtransform exch pop
  sub exch div
  0 pdfWordSpacing pdfTextMat dtransform 32
  4 3 roll pdfCharSpacing add 0 exch
  pdfTextMat dtransform
  6 5 roll Tj1
} def
/Tj1 {
  0 pdfTextRise pdfTextMat dtransform rmoveto
  currentpoint 8 2 roll
  pdfTextRender 1 and 0 eq pdfPatternCS not and {
    6 copy awidthshow
  } if
  pdfTextRender 3 and dup 1 eq exch 2 eq or {
    7 index 7 index moveto
    6 copy
    currentfont /FontType get 3 eq { fCol } { sCol } ifelse
    false awcp currentpoint stroke moveto
  } if
  pdfTextRender 4 and 0 ne pdfPatternCS or {
    8 6 roll moveto
    false awcp
    /pdfTextClipPath [ pdfTextClipPath aload pop
      {/moveto cvx}
      {/lineto cvx}
      {/curveto cvx}
      {/closepath cvx}
    pathforall ] def
    currentpoint newpath moveto
  } {
    8 {pop} repeat
  } ifelse
  0 pdfTextRise neg pdfTextMat dtransform rmoveto
} def
/TJm { pdfFontSize 0.001 mul mul neg 0
       pdfTextMat dtransform rmoveto } def
/TJmV { pdfFontSize 0.001 mul mul neg 0 exch
        pdfTextMat dtransform rmoveto } def
/Tclip { pdfTextClipPath cvx exec clip newpath
         /pdfTextClipPath [] def } def
/Tclip* { pdfTextClipPath cvx exec eoclip newpath
         /pdfTextClipPath [] def } def
% Level 2 image operators
/pdfImBuf 100 string def
/pdfIm {
  image
  { currentfile pdfImBuf readline
    not { pop exit } if
    (%-EOD-) eq { exit } if } loop
} def
/pdfImM {
  fCol imagemask
  { currentfile pdfImBuf readline
    not { pop exit } if
    (%-EOD-) eq { exit } if } loop
} def
/pr { 2 index 2 index 3 2 roll putinterval 4 add } def
/pdfImClip {
  gsave
  0 2 4 index length 1 sub {
    dup 4 index exch 2 copy
    get 5 index div put
    1 add 3 index exch 2 copy
    get 3 index div put
  } for
  pop pop rectclip
} def
/pdfImClipEnd { grestore } def
% shading operators
/colordelta {
  false 0 1 3 index length 1 sub {
    dup 4 index exch get 3 index 3 2 roll get sub abs 0.004 gt {
      pop true
    } if
  } for
  exch pop exch pop
} def
/funcCol { func n array astore } def
/funcSH {
  dup 0 eq {
    true
  } {
    dup 6 eq {
      false
    } {
      4 index 4 index funcCol dup
      6 index 4 index funcCol dup
      3 1 roll colordelta 3 1 roll
      5 index 5 index funcCol dup
      3 1 roll colordelta 3 1 roll
      6 index 8 index funcCol dup
      3 1 roll colordelta 3 1 roll
      colordelta or or or
    } ifelse
  } ifelse
  {
    1 add
    4 index 3 index add 0.5 mul exch 4 index 3 index add 0.5 mul exch
    6 index 6 index 4 index 4 index 4 index funcSH
    2 index 6 index 6 index 4 index 4 index funcSH
    6 index 2 index 4 index 6 index 4 index funcSH
    5 3 roll 3 2 roll funcSH pop pop
  } {
    pop 3 index 2 index add 0.5 mul 3 index  2 index add 0.5 mul
    funcCol sc
    dup 4 index exch mat transform m
    3 index 3 index mat transform l
    1 index 3 index mat transform l
    mat transform l pop pop h f*
  } ifelse
} def
/axialCol {
  dup 0 lt {
    pop t0
  } {
    dup 1 gt {
      pop t1
    } {
      dt mul t0 add
    } ifelse
  } ifelse
  func n array astore
} def
/axialSH {
  dup 0 eq {
    true
  } {
    dup 8 eq {
      false
    } {
      2 index axialCol 2 index axialCol colordelta
    } ifelse
  } ifelse
  {
    1 add 3 1 roll 2 copy add 0.5 mul
    dup 4 3 roll exch 4 index axialSH
    exch 3 2 roll axialSH
  } {
    pop 2 copy add 0.5 mul
    axialCol sc
    exch dup dx mul x0 add exch dy mul y0 add
    3 2 roll dup dx mul x0 add exch dy mul y0 add
    dx abs dy abs ge {
      2 copy yMin sub dy mul dx div add yMin m
      yMax sub dy mul dx div add yMax l
      2 copy yMax sub dy mul dx div add yMax l
      yMin sub dy mul dx div add yMin l
      h f*
    } {
      exch 2 copy xMin sub dx mul dy div add xMin exch m
      xMax sub dx mul dy div add xMax exch l
      exch 2 copy xMax sub dx mul dy div add xMax exch l
      xMin sub dx mul dy div add xMin exch l
      h f*
    } ifelse
  } ifelse
} def
/radialCol {
  dup t0 lt {
    pop t0
  } {
    dup t1 gt {
      pop t1
    } if
  } ifelse
  func n array astore
} def
/radialSH {
  dup 0 eq {
    true
  } {
    dup 8 eq {
      false
    } {
      2 index dt mul t0 add radialCol
      2 index dt mul t0 add radialCol colordelta
    } ifelse
  } ifelse
  {
    1 add 3 1 roll 2 copy add 0.5 mul
    dup 4 3 roll exch 4 index radialSH
    exch 3 2 roll radialSH
  } {
    pop 2 copy add 0.5 mul dt mul t0 add
    radialCol sc
    encl {
      exch dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add
      0 360 arc h
      dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add
      360 0 arcn h f
    } {
      2 copy
      dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add
      a1 a2 arcn
      dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add
      a2 a1 arcn h
      dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add
      a1 a2 arc
      dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add
      a2 a1 arc h f
    } ifelse
  } ifelse
} def
end
%%EndResource
%%EndProlog
%%BeginSetup
xpdf begin
%%BeginResource: font CairoFont-0-0
%!PS-AdobeFont-1.0: NimbusSanL-Regu 1.06
%%Title: NimbusSanL-Regu
%Version: 1.06
%%CreationDate: Thu Aug  2 14:35:58 2007
%%Creator: frob
%Copyright: Copyright (URW)++,Copyright 1999 by (URW)++ Design &
%Copyright:  Development; Cyrillic glyphs added by Valek Filippov (C)
%Copyright:  2001-2005
% Generated by FontForge 20070723 (http://fontforge.sf.net/)
%%EndComments

FontDirectory/NimbusSanL-Regu known{/NimbusSanL-Regu findfont dup/UniqueID known pop false {dup
/UniqueID get 5020902 eq exch/FontType get 1 eq and}{pop false}ifelse
{save true}{false}ifelse}{false}ifelse
11 dict begin
/FontType 1 def
/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
/FontName /CairoFont-0-0 def
/FontBBox {-174 -285 1022 953 }readonly def
                     
/PaintType 0 def
/FontInfo 9 dict dup begin
 /version (1.06) readonly def
 /Notice (Copyright \050URW\051++,Copyright 1999 by \050URW\051++ Design & Development; Cyrillic glyphs added by Valek Filippov \050C\051 2001-2005) readonly def
 /FullName (Nimbus Sans L Regular) readonly def
 /FamilyName (Nimbus Sans L) readonly def
 /Weight (Regular) readonly def
 /ItalicAngle 0 def
 /isFixedPitch false def
 /UnderlinePosition -151 def
 /UnderlineThickness 50 def
end readonly def
/Encoding 256 array
0 1 255 {1 index exch /.notdef put} for
dup 17 /space put
dup 14 /period put
dup 21 /H put
dup 24 /L put
dup 23 /M put
dup 22 /T put
dup 9 /a put
dup 20 /b put
dup 11 /c put
dup 1 /d put
dup 6 /e put
dup 5 /g put
dup 12 /h put
dup 19 /i put
dup 16 /l put
dup 15 /m put
dup 7 /n put
dup 2 /o put
dup 25 /p put
dup 27 /q put
dup 10 /r put
dup 8 /s put
dup 13 /t put
dup 26 /u put
dup 18 /w put
dup 3 /x put
dup 4 /y put
readonly def
currentdict end
currentfile eexec
f983ef0097ece61cf3a79690d73bfb4b0027b850f3158905fdac1bc024d7276e
0a12b7ddcede59e3601ab4509dfe0977ed5bf624ebc1f818c45f1350d41b052a
72743accb053eb06ed043568d3196a30bed220227e2a15bacef508449221cf33
8a8666e92410a9aa91d5a31900a93c01ec21742cd14dc46bffa111ce10b78ae0
1abaeba7f36cdf79a4733245c63f6d36234d6b0961f1ac295d6177931b9ed554
bb5fc6741a63c493daabf03d753c7d2b8e8c01e3e280898f810da5985212c8c0
bbdee4e8ab9b22bea83671c0460443ede9be044168f8ab50be5874d46660f1f8
241cb261280a68ae2cd60e1648cff45c0ba9b15cb42f86217172a5b855265c21
4d4b954937d11b94b7b98738393ce09ce40802e512bea7714fe6f163d1b27c8e
c87419fa91767418abc44c94a3a22f97f856b0a4729be6973455a7f7ae72c671
542e9e74258c2b8b2ad440a1b69bc7de2e54ed6a96d0bfde08b35f6fbf739ae1
8676c03800ff3e63c6fc20927b3158e8d2cb6644eaf7831c6bf0e9b39aa14145
e721dc46e792da9be78696808fadf24136f9da0c8003cb34ecb8af2b7de9e033
545fbca53d881eaea40c638396c8d3b08b6e2b8f7d6188d055d6924bafb0cf7e
f8bf2719495988b0efe373dd1aea97b0f486d0555e3a62cc1b36024ec3ada21b
fe1629acf431928facb4ead9c41e3d4cb50ed2f651d2cb6ca8d0b1ef49d9e214
e06cb029bc1a40b2052938f6bcd05f013d9ed1edc90bdea459c4483ed0d1470e
30ee0a77ecfb585268a94a8bc6be7d28e5746525107c0a3f05fb5e34e0a21572
14be2d95a46fdec2e36afd180688fc710c92b27d69b2ff8b1fc7f73cd5526270
e5bb585d7674a351d9bda5dcbc17b40d465923103f1d02e7446d949002657763
c82c8fe0372afe94104d148679b4e5be01def615b295d7c25e24660b2a10dfb0
b5b96fc02bdfdadc10afddd821fff6caf17f11d6a7cf157d3d7f1aa25a00cea4
1207c8e160663d23b16d2934ffe6a6c178d456facef20fd46c4b33f6d1ebf103
b7cde86d7aff74174d2d3f5820186c696b9245f97554b7f62411429f1dabebf1
ce4abebcdd2a4ccc1c06d6ff8dd9d7f935ba5218765a81eb3c727a40dae317df
89cb3234b1a4f1a0b16f88ed1684d3106c2a6cc18aedd3b052df1a2ea7ccb8c6
c6111abed60277aaa2b91f1da4a83c0b2d4fae8cfbe2873b7f9ec2e9ad05045a
bd1133b95f70185dea97f1081565ac65139ff102004b00e1e77023782a68a752
088f8d8cd2393eb3f649553f0be59b83687f4425290ff1e334794e59ab4dc73b
26f1beac4c5d6d4d507dd7d13b8721144d28b82eba624965e3d8cf9334083a6a
461277026b05583f96e489be17dcfaad73cc5b9c6021527879f2c194a5bb1869
9cbef3ea4e14950e1aa56abbd38bf509629e8a4f0edf0946a47aea100a088151
a9e296d1b5d7688aa0b3b121fb93bd52789d22fc32d645230419d1df1d106a9a
90948fd443eb64a212b3595a133a4a30434b5074ff14f69368de4e0452515257
aad6332ed29556152c71240df8a6746486d28c6a1315bc5c5ed08a5192c2fd7b
a4ddcd7496139ae2e6e47ac4971edc88a81e2056ff81081b72cec34df2e6bf17
20bc5c6753ae32e31ce0db86b3aba65f26335a57f2f12827f7495183427d3e86
1b6ba27f7157003a92a9405c8755f71dca78e6cf0730fe59504cbe903beec227
65da1f35eabc756bf32e9980eed40c0d1a201e12a71b63171df7ca971e36c03e
8137e0213fe675b392ad8b3232752dd3864c82f9ff85f814becb6fc7510a1e99
17bcf12a90c4ee29e036db54278f2413731df21833d1f8149344b46e4c3fc2fa
9647e76b3cfd81b4fe88643e427e7f6d9b01f99659e531df0c43b4f44ed236f1
17bb00830dc10a5b1896cbee06fde9b4fd9b0b138405a0bb83d78ca5546a2b41
490f5322405f0ea6276d9a13a63b98c59cc9a0428472759009cda518c4dfce24
49e27df9caac365a6ee3a8ac451167c806889760c404164f941d035b6a1df55c
44ebdda9484f4da9b07c059ae59617c0e86ffa71b9a70322acb3b60071128799
46f950e04e6b634439b06e05a9781a9ca6b9cbfaf508a835e2daaec957d95fa0
031f9ae42c17cfd5adfb81766af25ac5237818909e284ae4a439b8b2a5050dde
be0dbde491d135155e98ab579904d045797ea516dbaa4529675a381372fd437e
53f9372dae38f0eeece282771fe7c3d1e68061cc242e4640131ebfcf340b453e
4868ce4825067dfcc88c7d84aee3f06eb202a89979aa520e501288e93f742fc8
6b6f43e3bba4430be40b099cb0535504f966cf50fd9ba9fd358fa184a39eccfd
4d8e5c4ec35b448bad9cf5bdf15b729a4137a9618a5a44db7d9740a15e0da9c8
02b428d40ed5401ed76095c73512cb626630608c74143afaa7be85562aac8d81
48a5e603e3b69b89706b0c1cf5c85bdeb32611221c13325835238fee492e4a08
bce9741094c4cdc3edd691e82d224c7866590510e2c7cccc07e11484f62d7930
3fd559e4e511eb67bab756f30acecc560f5def3902bfb52abfb7aa48e72f2732
b7eb73c0123f6dfe97cb69897c1db3d57ff05466c3cce4730e04e921a5e56e8a
dd31933536393bc00b3ab3435ab950965a752b913bfdff22a8e7df7bc441e5bb
3a3192bea8a17829faa529e56ac69e5a25a6797615d5455e4b430627f9c219a3
64bf0c55669cb872e403ed1cdffc63cf9223ab581bb9d7967892dfef80da723f
18e199e0b57f12ef0210326aae328882d982392dfcd40e029ad3f53dcd820b4a
61b580bc3f1b492453f5c752e05c705bf8bc05485c5499f804a6ed2a28bb63bc
7e80759003cc7ef0a1d9d51dab1f785d14eb86bd9a4f4221951da58fe7263e23
e58a2414dcedb6ce1943f62a65699080bf568cc0c67134d8728963466de67133
27129138d203ab8db0079f63349ac8ea689ac7615d866b7f600b2e91333b61d7
3c98401b1cb0432e90fa7bd87d9f4fdfecbc2dd5e5eee5daa7d7bd959e41817e
17525a472ac035c391b918d549c38bf2b2426798fc27af235a725ddff5dc79af
b59198c94528a36b8c7cd5683f8af50107b45e02fda4c787b4f14ea4e663bbd6
15be5b30d6979456f6191b5051f458bf19c91ac99a9a8505a03abedc243ba287
2c3305b81288a79f5ed8452e2a2caf3fa51208946c72b97e6d59ef74bd8b96ce
d9de45d7cf76a6891c7c0691298855a366737da9be57d98c25c7415122c898a1
564a052036a3aa550c2bc83478c4e15933de6e4aad64b2e97c640a2e8a14933a
baf85907f09588cb05432f716f05efe4a669d16c881dadc0faf5a704dc91f500
6e512a61372579eeea5f6076cb8048d71a1e4a3097bc27433bc3613ebd8291e4
27bd9cf83c0969562d5363662f74f2ecd57071c4d331a26559bf3e307d0e2d1c
9a90a3fc92254d2656555dbc0c8c3502985a00e705213e4522d5eecccc5f94af
0f196501250a4200b04b491f64388f7c3aa37970a8a5bf78a072bcbac61cdbf0
f95dbd13b8defacae1a53277fea4f19f829fced3b4cc6e209bc2616b9bd7312c
87d78cda5c9f6bca02595086adb6dac9b7bc6c9fca577169940fb58c818a3757
5de491222128989965657ea8b5dbd96a697ef71778109a1781bd7ddb9b2132da
71b3bac95f6f69fc615b7733d709402bc7fa0812d18aa22fab627f91baf4a346
d8f103362c0161a3b57d83856c63cc7150fa2ec1ba537a4c608bc28c85d388bc
f4105158f0c9d40a573bab28148104e2db167ff009d34134008cd1ab4cea4091
c04dd6eb2353686278cb190506778602b0a642d3997caa982a2b3c84f8bc97e8
3a177fbe6c69512014cbf7ab75d5a35a0521a2d1204d7877f75a8b0816da0bc0
58c0ccf411b939931bcbbcd1d3d92b0fee9e58012677b1db645c14ae63b7c4c3
e4b18b890802aaa72c0d8cb771ee4e46ddb6d714894aed7816d7164799b70d7b
64e0a50b979c3616590b871cbae60b9449d02fab57655abd48843da96359d608
7ce297a26e192491d1cb8420d7cbf1dc66b68ab4299ed1c500ebb26de35f9563
48d497c3c0858e812fd3d43cd76a41e24f19752bbc8a4a69510c9381cdb8a230
31f8c0a914db40a659a5b51e19fc9024471cce4e65cbab05a3562a2929398879
67cbe49331cb58e936a2b6873d3dedfbb378414914a2b78db4daa180a4b40a97
2fec68f931b75f2109fcf824cc7439ea693c8c080abed27376461dd5f86617d1
a931cf1caf206e872adf0d8b6e35499fe3df6d3833dca2daee3805fd76f7cc5e
f2ac6f05134e8da55b15204896002803ad497e67c2ea83b2646bc13a72f73d64
2ebe4b1d5b00a444744160f3341a84335643e58ee6c64acdfcec21bf506a6a30
b70b1fce06b97b23c767e7e429892085fbff2996aa68e4776b76de0f66edfd89
b015cc3a3e4d70cdf3bcad9d48b4e17b97f568b0f3b1557d003cd6f087aab912
a15e88e51f6e33c8c8b2ab69fa8e81f09a75e0059723f1de598a20c567e681b6
0e954bd6d80c7515870bd6158eb93e8af8ae71542d681895e2b32489694f090e
bc5b560515048626f803b996baa342815b5adfc437dace01d549a6319eff5709
6c537c9aea7c3f8dd978d42624304a68ef2427dbc0acd85a26960f10e348a30c
dc46e46dc16700f62108fe6c35059759fe69c729edd6c91e83cd49535e16746b
6dff037927de39b77eeb86fadd9ac5c89268c3c529fa1747650cf9e16c7626ae
c25817ea46c1ab2b0a7a9c7ba33087db199adf7594c297a938ddd7ad595c6942
552ae76711f444b5b833a92cdfea0462b6766685359cd4c2afe4114d884b230f
dc86d680a9b10a4333d68db6ebc595f86806392857b55452e44288a42f924754
c22778c6d7bfc3d4337bb3a8f68055d0d6f5053700b784c480509caf63336c68
7c5bd339757008be54c289a10e62d5c83eee133f32168a68aa259e8247d6afcb
25243df6ca8c238ea64082265560188e73a47db7603a1802e7ed3693a9b7e5ed
7b0332171196792cd5272b640c8a5363978a87f58b9d1022d5e7af38d1e45dba
bd89b095eb9e581ce8e9c314a8152465a4663fd4a7ad1996c08afe96d3975d67
fde3aef4fdbad38c739d0f1bb4584f919b4b5b8a06aa94bc3a4162aaaf01cf60
7fd24e90dd4889795aa0fd42e4cce9b0c4323963e288dab83c1d1187c1251d77
da1c6602311cf8a73e16699d6646bf62cf68b3da3855648508edb97cf3614ed1
141d158ce8f86e055e9034fcc9c77fe4f592251dca7e61952859567c6ff4fa83
15b554ff50b48bec4d99ad1221b7caa1d47a8f430a07d49f561296a74277adb9
c21c8b4ca1d3bf3b671506f71d8f88d37ec1b03432c2bcaa337659c35747b0eb
1721073e4e60e93646c719bc4e27c5b5fed52f456f43158ad6ba09e9db6d0c17
fa75bd7a80746258f7725116c37770e261c9bcf7f578f3f12ec7037c125fd86e
4d38ef23886e18f4e206397006c8c4ba0105e10fcc254a718e3c8ba6dd71218c
4768fe0d8efe2e01454dd52ef33080a1313911ce3e0afa57f5b74d7caef2440f
f148f3c8bbe0cb2418a0367dddb217ffb47fd5766ab6db331bd9d2779ceac6e8
e3e6562b79d947e687ce271f8f024c5cfe61e3453cc7ca45efc6b682d2da8ace
dda708fc65b668e285e6f542b9fdc071082076c4ec2312de40214f8616ac615a
2669bd490e89d5c125d6c0d6378113f4d37f1d6a06c225c7b0e879746f13607c
0a4b98b7d77ca29572495f4edd58f292ca28417808c8e60c3dd8b1a9d185cc80
5784e9a1ec1f290197637cb2f1ef65d1b114bc0e99a9d3070be7199f3d30db85
cb3b65eb8cdd60b44567730017f4f851d4b15a15bf4312f79c05d5ea03b1da80
1149fef5ad43eded70f470e62281fda1df9ef72f180630b3b1509eb5fd9c73e7
f02fe23f554e5b74007d6384f6255ea4bdd2a6eba0310eda07327884d26c59d5
3d38f02b11815e8adde0804c621d6cbda143ff30856063abcd0059183828625b
c486f27c475059855c9dcdb5831ce58532e3e6984b63b690a27373d7d5e613be
666ed52d9f743fd3c373984fbfb8ac8040dcc222ddff4a2e1f6d93f64aabad9a
286e3e07679adc853885c8658e37b0efdb68fe51c09ec2b6b69735b84d2aa481
793f0e5982e006d985c0c2b8d394b7093a210168e58688ab1c07b99b857e9052
3f90ea3f4f4202f7751dc55dd7cc187f4afacced589cce0189545f2a26c9d283
b14ab2aae2e5393d416e014ad99e27f8814c0b1bccd6f798865e243bdc9408df
f7e6fca3b515e5edd3af9ac11e4bf0a7b7a736959a4f48d4e519d069263b0af1
43dbf431cedf2ab7d4df2cacb62627ea46e77e20233ede4166f291a3a19f6227
1ea68be133a61b6342782ab58310c4e2b08782800f48d311a7c15d1a6d3f7c6b
5bf2d91cf23b931793adab17d9f085a9aecb9d4df2c4c50c5329503c4a8ad83f
df446b306c56a2ca97bd50f359280415f8cd4bf01817da0f01a0e48bfa4c7a1e
85f052a03369b0ad7eb0122585bd4445dd53912b2d1ee8cbd9b7e2716166790c
32f4e068134102aeedc6ade4d5db39ac29f424b0d5e327d081990adcfad18f6a
b64c7f199cddebf0490b10847d158b2151a8e79b707af40ba4a38c8c02fc49dc
ffa7e2813ad7741ab7bb29c93e146d81be2a2494791582618f49aa9f904f8faa
1ec63adb809cd473ea6743509617fdbf260d4024b4101d962f66f361d7257804
e354e050004155cf050ffc6adfc28c4f742a3231c5fa37c7c826985c5099698e
da86f0a2baefff000a4e74597e5bda20f8c36f22ddd94ff45e16ac91fd250eb9
d8d0971bc4bfda5b6c0c14d850822031fcc8f231023a579c09493ff2ac9f72e8
1b4c0eaa64fc3401b7e128b2642aa708ef990878091956a777d908fa0c4e1f2d
a3363e098a28b6f141ef68258e2f6ae3ac089b3b89de4379a0da96cfaa81a7fd
fae2fe9dbdaa3b21435793e464baaa346a722c385e71398949d32b76c6cdef0b
05c752130d43ebc45a1738f06281097150423f885470928cc1153cb01b2295df
e17cb19d3b4d576209425a806b98d83e80158b67120d6ea0a65d94582e248d3d
d8ad826bbbc00b9b9dd0f4d606a65b1a0ba8eea83cff745e222e6f4645055a9c
bdf1d99160e0e4854d989f07cc3f393f72af97c3575d6f1d8d4312848bc72bef
988cc436c23f4c6a2a5569a79d04a0667611a3b0f2e2b8ca0a6ce0536b0e459e
21dd3d74d8a94be16cdb3d65a6534be608688944c0d68c62e39899104ad6e587
ec0f3fc097ce54d3e25c9f081dec3be6c71b714b9f92c15517dfd763b9bf0496
d601fe4690a9a815e803221e007a7ca74743f679daf6a626af5a6525b394731f
ebbe7cadb5de910c2163e640acb041736fe4e508dcb5c7d87d38e12ff80fc903
c26c480b567f057b193f5d4ba352697b9481d780d94b815a7d96ba6dcc34e39f
43caf780d101bd73488a88d213063432f8e6bea7e7248d85ab48b576ee702af9
364c81f7d5c74ddad8315ed4345444e0cd92ea23b4394073178807892d2925a6
a43a75c68881385a78d9d5582d3f3f8bae87ae177ea46dcba9af17217906204f
751a358cd8a4d8c95ca76651271963b6d2ffdf282b653c85ede30f9c8bb5f113
528e221aa1a6507364f74ecae922bc09e6c3f42166b2118a819638a85560c6e1
eb7bf2893357a81571201a2bc31a91ab89489fa2050d353039a7085aacb83609
825ae7392a84b6325bbf17af46a9a3eb63ad14bb387987f6d756ffc59a2a0893
7538a0efa89ca08f9785952d2e8bbba0e6023ebb8fceb5abcc3c0c3c1b980255
861d991fbf27e70686fa238e92ca9bffbad61bfd48c5b8e8aa8fde96fd9acb2d
946b69a51137c905955ceafeafea0acb8a0c561808ec2e0d4fbacdb7ef9f9abf
afee72f759e8208559c232ffe5bf6cd3e7cbe88ea579e795455f7c25f4343455
06d98be333bffa7f7cf1f83bc00e38d2503ceb483519e3b1e5cb7751c00bd2a1
3c385e2f88ee5df92086b57fadc621a1a539ff102d4fc4c075ab1d800eb1efc6
fabdc04f81065f0ef3aa5b947d904410962f6533c1aa49b86178ad45e35d44b8
66c938876f2bdf1dfb28d793bb5d049df0cc3e21b8ae8f9b75ac06f00759d48b
f39c61125641612bc6032f5b6046d85ae9c7102b99b93f7674e80f96a1d74c13
68d2fdfca6e8535a9d80fbaae20d681e1918b4af227270f40ee97fbaad4a4216
908272cd9767fce64130744d0ac38825384bd51bfe19a150b55dd390020ae359
29d4026d4d8798cf2fcabc5ffeb88f20129ff22baa1bf3fc412b404234554507
5fc332a91a87c3ccaaba8c201ac784fab723c1371991d5a4c5d865727dc7170d
876a83dd01b10c294e651e39a2d3a7c7de70817b0508f612856ddff87bf404f4
c750437a96608c130bbdb8dc14051061957ec0976ac3b58e117b85cc17f7be4d
d59a34a81ecfea08529704d8cb73176ea03c1d873f0a7acb41d533c8d68dbb3d
9b879448ed2e52a98957c41682fc30a002015af634229c4d5d6b900586a0a0b0
6b1fedaf188610cc3bfd97eb4261460ce68154b3a5a19a218bbf3035fbc64778
89c2be397cad1e44c4fbbf3260bf85eaea01ca97d02b4c366a44fd08be6f197d
f8243ca699c2b75b54756ab361115fcc5828dec91dff364db969960569e59a1c
3fd2b76b4f88fd9309f8c9962d02ac778dca69f07609b0b9961ffac6d942943c
bc2e3682879841df4f1d05350302cefc029100f934704dcec7e3f15387153325
8ad2b5b5ad89d153f53be6390ca66461b84fb405b4722d3e3a205ce3bf339018
b339f240c4956edd92e16ed988b46813e5e39533804efbc6e426304523b82073
d9f296b3f8283f12dbb66157440222a888acde1eef4dc861f9e8d0e20c5876f7
4e99c1dbb0b5fe81eae326545e84285864f90353f9c1c21c166deafc24ffcbe1
a19522ac8cbabf3bb73c36bda0238a19da380a6ba263cb28f99d3643ca4f4b21
ebdb9e19f1d53947c8f43a22320f8eb83f152580d83dd6cf230e30b74d2f0bf2
6d6b621865797b989714ddc45136974dccdc37baa1a52d021544aab74521e9e2
ef0607d951b1e4cbe230a9a1095df65774af0c2a0c0f1770dad9e054dc06c81d
30801a927e525afce8cb8d753bfb1fc2b5d967b9e25c7cfa39bf6fb86dd482da
0d871d5c8725cac7b44dcd5c3059f39a4cb216177100c0f99572ddadf8d7d537
33db55286717ce9ee2a12357b901b675c566909a0b4c71bcbc7bbb7d36aa72a7
018895b617ed93853602a5fd52daa01da6d6e3b713b7fd9d6f75e05f21857211
d6ed29349ff0e628c26df07d1c079e556ffc60585ec8e91f38c9b4ef0a708559
b4cc4155ff42c48c18731bd231b2dcb32399943e3fd64fb66d3011cc85e9fa20
e28c741303d5b1f3b7178753cf97364716e6bea337a89ee47eaf9b93f938d9d1
0d82d4c0e3927af3c34927fdd5fab439d303d997637e2d21725bca942bad146e
4df93b37e5a38e4da57cb1d6e6e278b17a82644c800e6104eb2518c03ea9b8e3
f9b7611066ef9afc58b893e3fadc53835440a47d93c7052ca4b617c1d958c693
ceb60f9a2814cfc1b4a24b32783b389678bdd14fc3ea2124f124afc5ed977097
af7a1d3a4d825c55f0842b2ac566e43458495b6f51c011d7e78818f6d934203a
74a961618625a380923926544b7c13c14b2180f3576cdcd4f2140bc90b2ec84f
1aca97f147781866d711448c1dc8df1fcc1a1769ece2ed5cea053795c0cbfb72
04dc61065c87be00d9c0527d5df881708fdbfb7fbe01a933775548eefb736d01
4a560cdb4313678581a3b1aa73d546869301f309f189c2df29f3d4bebb3b5a72
046354c2edd273c9794c3659bc72fe7fb7442e75b04fc197a49efc2ea39ae0b5
d1dce9bb509b5085445a66b6a59979c26412f1d6f5ebae84175ff08a90c9be44
06797389c439693e2fd2f2c26d2e9dea41c505c32477ca50fc01dcd53d388e27
cdfd4d73c2ac2fa03b9eb934479f0419ef50036b682c9ad8bfdaa3adf80a03de
9f29b7021cf0441deec0f002fab57da0f5be89f5da4597a2523a2e7886589002
e5cbbde0356b391148b5502eaa3b3689871a1cebe9b8214992f5349ede7d799a
57b85d1e2ae706f8567efcf24081165f53810a2dc9568a263f69c40eb55cf317
82da10dd970dc79f6593f1cdd9ce552de6c7c9fd3ab21169a2e487d5fa959d65
9afddd071a0d756b5c7debd602cf9ad3e6b3dc3f29d954cad22ff28cf333ac67
b8793f01c6f13c4ae2b6732d60633b59c2d9296ec77b6ee630906adf73ef8603
3317cf59b6ffcf42fd7a68133f0673a5c91b8e0ec7b88872e9ac8d0aa904af60
00799d57e1dccb74496e345dfea868ad7498f3ec7b85558a1fefb6f03c7d5365
cef02b044b220c162c530b8cc899887f8846084c7b4fa1dcc631ba3a3773fa22
443097b47852b119b42df9d58ef3d55ca10f38b04f378562b3bf03140e25544a
77e66cb9589e6f9dc0a11b6c2a35fac32ce9bac552dc54270bfc025baf639b8a
a5e3dfda4908b869969bd633a9b171ed6a04a2ee6e3744d7a348cdf09dacda62
5269181d8d0fb84b468d2eea50fdf69324bf64ab1db3ad0fb2fb9583937f0be8
b41f14a751d7115adf2d329db753cd14534cc282f2b4a4bf497a4c7b69cd25a1
fb33c5e91796b885176284c77a119b50b077001b566328fd23170e4ae611e342
6fc26443587e3982cea97c79fd63a4dfa95efee48dd81f90d67e40f283c27947
d0f0823d2d2d26210e5243d2029b2ff059336b57b9b1334b0b615bf357c6a732
c8d5165f2c9a6f310e48a2e4d7dc965887b45c14c9b744bd98de8f33071f0dea
693ad64a55d03b2891660d09775030eb5c0e6e868ab1b90028c373d3448851e2
25dc9eb442aebb5912ab0f3b1107a7d96f9d23983d8a6cfedd589e59fd355ea0
aec2a448fd9d254d39331cd80dbfd653fffdb2702cb848144c33c28d207adc51
097c28f754521e715be8b7b14c4f86aff04fddb0bd52247d814192a884e5af3a
8f675cdf0c9dcdee0668773c3a3673af8f51a71bdfea19d0bde8a2a23453164e
dbf01c932db93128b686cc6fd9a1dbd506b6c52664c5aaa01901c5ac0a8275e0
ff4ec66ae3326dbc1b3b60c4488b6af86fbf30ddc1e3e3a8d63d7682c222e746
05c95af3327e694f3b3c1600083f9cc241f97c5013c9a0588c715eb4dd00944e
824e43a7a1c1fd144d1098628139034731eb1cbf633184cb857a17855f277bbc
18751799ae28f48130cbc1ed559ab1a5abfa2576d59fa35772557a6fb3d15b4a
de8bd38b763be0f8d8166613cc37dbcec1d65aa06c7b9f171028fddf8b55093a
2fa509ce882054682fcfe32d510012ef5ddcf39f0ae5ade25af279829f8d47b6
5b89a40a71ab70c2cd961aefb7004d3910c190bf32137e4d9733b971db4616ba
789c741efc39c26540d3228884b4bb490bea1ab957682d250cf95e1d41c11662
3925e7778755c11c654d42dfff1db2a49c5b57c3df98d942373519cb02f36759
8997028e11c513a99b4abf115c61e2daedebb709068ce06692303cd0be482289
18a12dc126af0e4f81766acf9a84526add4d2fa145cb5452c09547de307b352e
141233cd8aea9f965070a2e6321a795f896c0cebc01ce3a15a81f14c14d74aac
a4ab090125fecc310410da79bab5dbe07e9eeb2189788f491c457a82abf7f79f
427932c8ad38466431e28659056c3d5a4be02c8d0d054bcd4f9170aa7b7b0d2e
9a4564af66eb7372fe981bf441b68cf8247d11fcf0bfeb6453f9d2210dc880b9
b9af2bca1dad558c1be18eab687f453d4aac976fb9466a6602ffca1dc852a56c
50556d777258a7bc26489789fb4fbe2f70034eef6174244ebdcf514c5ff72391
d097750ac8a9fcfe6c94af17b3a5f2667ca2a02e7f32424ad5a7d902751f7c41
c9a7fa5fae2d8d7396f8e586be8ba8f960ff3fbcbe783e5ece80def85cdf792e
33459d996a28775979b335a8448523c0a187dd8f3c0831231231f2a158a7b764
2593932c9e0dce8892ae708b9458993d580656e1614f2d076f256a680ccd3d37
0e37cde46dbaf38f096b032170759ec0619cfa0389b17568017f8d2811727965
c75eacb1bf1b179b69567b0ed8bdce2ce95e98ec7a9a573a79ccd5b4990e46d5
17324a06ba418b34110feeabfb71c1e43cfc1650179fc1e5f65fef017498b83a
1eb5fb5e340a1b19ef7f10fd0422f6e7f640db9a46762fbbaf33e2eed637ee9d
93cad018e33c4fc821212bb0f38f2251827a46f38c38c128dfa891f0b8ed1405
4c651b735837a0f862967c3d39912e288dc3939816e015e8be9ba798f68c5e89
a4184aa18392352bdb53119115b1a100e0941b80fb8017dd198c7d0629e72f27
da2d8ebb59de72ee46daa03e57b12513988f2023484d9f0480126a378ac134a7
5c2bfdc4df5b8d8fa77ba3fe2da9a01ec9427a00487b3a81b50a118c528b77c2
2b57265e5f915a063fa3e8bac0ff7cbea9ddb19ab8390775df6049cb85921457
cfae8a868bc6584a60223fa19a363f98876ea3d1e8a69337a58ffd75c9b296ea
5485e343c04c72a53945e21fb479495d4686302f39188c01b036253ba0a18fc8
7aae335fa522a435094c3608cf6e2e37fdf5fa3f59048fdbdbe6c58dabafe941
a7af5aa4ee7b44d64df374780e9e2d691b4639e2aaef8c52de72b51f2bb6506e
5e98f8ae236d183c9cf250dee46d102d964aefb7b82ef32d19a03aa88ef2ab97
5f04a6cb5208f570af43f73d804843404eb835e5efe3e34887a37816ed3cb02b
13e91be5bda75a112d1d27e92e462ec516100ab117b2882993af81dfbb58ebb2
f5bc5d5eb98e48f73e88144889677b31d3c660839854a5c611a52bb493b64455
3e6948d71f94f04eea57f7d458d7d78bb278d83065bdd9097f252d39a9ecfb40
8f2229ad5edaf4afd518c804214dd2458b085d7bd382c7a1e697b5e0c1a47c25
e2cf084d63bf186635783b56e6b36e7da64e3f9e3e7135d74381d957c0c62a6d
2c4dda1c21a8e49979dc4946c3bb84680e4386750d4b19c4011759d84f90cf31
b268f0af056d8566e84939388ff4cda569118ed71a2cd82d28b44e17c8438979
5a4357f70f976891292e15448c74ce895be53e4212079fba23793f3c247827b4
4f0e39066964e756719c628e6bf4a5f080de8402d5d1c154785564e019f13ca5
b45b525b325e29f193557770f88ef82f8d7704631969d4ad624206665ee1d38d
7ef7a7979aa05d39528beb6b7764d88da381eb63f0cca2f797dcac11011445da
21da35e051c1db3da576e698451a0675944f5749e465faadfa4bfb09eba5177c
e8cecbe67fa06b74d75278d7f28c236a596a17fea5467785f345197a43ec5f2e
1b7e7e2151f287ad9181ac39c9771a1713f45b5ddbb402bf674e3eef369647bb
c37b3afb327576831021a1a38fc4840cc4716da8026d16fae600d543a3c4dc4d
7cd5baf19f1db2a24a0757ef6c3bd8047288c1436eda2bd3f9289e6f8b003dea
d7b0cf49f3aa8a56adcc26ae300976e1c84bfa04d9a1887682d19ef68f52b76f
dd0e03f64cc92dbb3ebeafbcc56f8a2a99af870bf7f0153dde4202ca45c530a0
562dfae59234f4e3287b93bf427fcaa8d236606aa43aff3862063c0bd73dde6b
dd3ab4a8c4d6ad9c24da288dacffd02aca90dfdc72444c9bcbd331755876f649
e4b665d69921097c364eb8b0562090e10f4d719b2b5afc9312ed39c77e91ece7
61c6c940133f940a74e5ce3c05d9703556d28a5839727c54800ad0e496885aa4
052f65813ae552e8dce8d6f73949d0fcf5059e85ca8a1c137d751c6b8a87a52b
198254d01258074227501dbe50de2b82bd2510e5788c46ac997c65bf44dd6928
ca9f7a902bb957e277e7380123cdd93cf75dd6c7e5a56f93f114b6e46e0407d3
ed544d781ef6fbfc704a035b7b737eb332457977f223d87ba6e3dbe827b4fae9
e687f6975731d42a8977cfa67f94e90df98ca790e89713dcbc07cf27ea8c4584
cc933fc342e5c5e740ee920ac3403d4deee426d35e1062a2cc7d5e23f568b494
95c8b4556a8bbb0480ade618566f537b440ce52ff7d2cd89fc806fc388e9d7fc
8bf15882a38ae0e11915ab03c272c8a312094938b9b4282ef3a321e3bd82701a
50f8a4380fb32533cf4a100b0f96475a0f12fe9ce7e6a41784fe7c83f05869d4
2b70febe4f60bf749429bfc4721acc4e17a961bd7da411471edb7a32f4479f2f
079239c9bedcceaf35119982d686545cbb1eb0e9f429e9dbac1b743d28d12c6f
faf8f98a3bbd60518803d997a56bb515602dd3a75f7ace8adf16a6ee79233fee
1d21bf40914f29521638aef27eb796b06b5fe274444e0833ab9a79bddcb33443
5b815d0af72964e8cc297d246c6bd6d78e0e8394d8359084963b01416db54a3e
3a6d9784320814c4fa99aab6c4934b76a26c5e014d3fd202935f2f9399dda83b
4d652ab89936578ac2c70daec483f69422b25472458417b87f2861ff90aa37e4
5c07ac19fe09a4c2d37c917941f01682e650fce1785d114abd5949ae733bdaaa
d98a802437f465bb7d2d1e0d4118d6ddc9aee8e08e606d9703c319001725da09
5dc1e3a421f0c5315e28765e9571982039d5313efe20de55e7b614184c4a1e4e
af4a89c62331c6f2511d706c2c4248c626e6474c450db1838f1d8b264e406d6f
85dc63e78936a3f7d84baaf49bbd3ba15c58fc4734fdeb13d1f1557f29ee53fd
bcca5d008c60f868ab756608ce889de583309a303cebdeed91e7c4922526f125
58d2e751ec11b3c0bea88065ab0241f9d1e4c6144150f92f917b629295da2e84
33a66b4a6e6c8571b684a675af7e77cfa6723f82dc6ac13a8a568ed06a519ea0
a2725cdc99096ac0ce941b93207ed3f5991241f709ef7f9e8b2acb77100cf293
452a1917d32c2f2a798af506a827be2d3f3ce87e3d920a0d8cf8e98a4bd3bd99
e12f4374e0f6ad25af32793c5f85b77e213c7805156d53eba08d9a84ba43abbb
a8202d43091436113d930a138dfdd15774397f496aea9172ff0302555658d3b4
f6926fc115bf3de066f2d3bdac9738ecb824713de70361c91374fbac965ed71e
e2aaf3a27a9cc5564dd26a4bf30dad76ec5f955915b1363ddc6bfb706b559fbe
e46f6b6338dd6a07ccdb23b33b0237c8f0a428fcbf6db62fe6906e4a593b4dfa
ff151b2cd167951a70f535394d84b7ad727bca8403cfd661abf9a72ca0634822
f0ebf66ed148fd7b29513eb151c8d76ea7b74902d76ef7a88d5c571873bd219a
9f7e60b5d6b77bbc1afe19165f88bbcf45cffa773fa9379259c61a930395ce89
109c5e3a14066dcf9dc8387209c84273ecac6a6cb033d54cbe4451036b0b5335
bc4b3a2c6f6a4395fdecf9c1b88d3b8840e0a94b0516c5821cdb3b15aa06ef3f
e3a2c4729e258156fb7ade7c1b8f673dc87a8c87d6229df03d88fdb8d7e122cb
db3c8e9eed4ddd03ef86bf2b6fb140187441e7d3ad4bff4bb61e57dacbb792e9
f4263770c169933f99eaa94f686169ac46803bf6324b8498c154ca78482224ad
28253607ce99680a755c573b8cc5bd9840b2c8a2518cfeec51a396ec8e3b6c3f
980a3896feedde1a0605ab8d7891736e2c9502b5e2b3de8d76da62afee99a77e
1b079bf6f92363e8a5b6e605245952f9cb351206b65eddff62ab5730b81d8531
1489f9b4f4eb4690844b47a8a2cc0881180d3b5bb8f6bd73afcef9300002c168
0503cab52a1c6c10b038c312a0c5e59c60072d4405937a8776bffb1c07d0a876
1bb4aab03dedb634ce0192bb51b07dfc815073beb441be59d2a5b29a64e559a0
d0f33022188ca9e9ee43530036e15604ac28bb7349b1f6b57ffea79982da0f9f
ef3b0447ce31ab3bbfc0c03b7a421a836b8bf793fccbe963059de30c4ec0ea18
bd7f3d00ceadc9e611bf4c1376a64087008b5941734d404646b9f698dcae3c90
6f2208158f670d807d7ac8509a38a95d16679d11cc23115fd80301e84f4b200e
e160fe96e54346be77e24998e679a0e1c0579135afc37c68c5163028b2c026f5
d22035539795135e468f192814b49c4967e4873799ae4fccd31cdf23f754ec82
068c2448ee44a452a0b4bf877a7c420006ce3e9e032d830e2bcb814e447b0147
3cf5933f6d82cb74e6d1d5d6211484ff1ab6add9a46397b42fe3c7b7cf6357cc
abffeda61f6aeab2ef6a84ba261f837fc8bffdbfb3ca6901c2b4b29834e08d4d
45a2dd4e8a51c229d30915ec1bcb1c5486a57eb7490c70c0dbfa01fd1c53c998
32c7e26e50265f54b8197a0316d30a5646f6e4a71d475e03460d81e8b658327d
b8a1b1437334d3a907947b2c899e4a53ffe9e8227b2d5420ad4109b2b136ad02
92b5ccaa83556e85b2018e629113c3e0d4d484bff995a484643f661975737cb0
eb80f2b1ab319b1ec6251c49ebe855e2d6ea533398f9b3148316210b46ed555e
f68a949b73f31a4457f45588654bf21d554b39eb23850e3a10c2ae0e7369c685
641f6d8f43936c9250768af2829cc655bc027fa640aa14b18a70aa3a75524911
45e6a7df0d81e0b7e1f3587ff086712368c48351d661add7e96a25b33f9f1f77
7cbd3ad42b6786c8b0ae23f5e61421a0b660b7381809f13664aea3067bad45ad
8451c40e07f38f9b6185867caa2a9ddc8c37647c6b6a77d281185db7a56c39cd
ab0ace10890f5c0d7807fc420a2d0948c3880dd22e0b6aada2580f9a635d12a3
05a89415a24ee12b834a6d01e9f1a756b492f4aab442368cc18c700e1016014b
12e2ca27f141ac3084ce37b42a4c41d41a3ae37aa2e40028aa8f3dd3f0b80df1
24f33e60d97ee975dc98338c7d2290544d8da601fdef3da00db855237a174cd3
dda0a9a404c749c849f5592390320053c4de8004c650117289b8f0c44cbef09e
2fdae18a593f2c7ae524cee7e3560e3116bba293c02937b0e95fe22687ee328f
eb89d6738ebd1604031d248ceb6a11f9ffa7b2625d3ad21050df6f25d1bb4f3d
5d269bbaf8d56d25ac40905ba0adab22ccfc7733dcdf3680fa85a94f65445951
e960e817427a9126a9c767f263f324dfd34841554bedd86841dfba7e43986958
d688da35786f0497a6d04fcbb6eef0d1e8d9575af1fdbeece6cfe66c574e6158
346774b185fb5c4e3bc71b45b5202f79210579b4bc35b21f60843b811df3515c
c0d81d665e7eb018619a243e72c29636b8d9366166797292ac7023cccacc9401
999bedc5920fe7f51458d13eb772d6500f471416f079bee7c9bfc25a0858b10d
c043cc9a219ab9a71ad62d68ba22432e1dfa7d7930f873a9af0ceca0cc4a4667
d1102a8a685adfdbc5a1b4cea2e9a94d1766ccc8f9e74213876f3d7bfbe09500
06b11f656a37641f9cfbd0b23c19dcac6d9c2b5cf0e38d8a58ed42c7d37d88bb
9a96ad2864fcbc6033bd464ca519c9e8b24e1033ae844ce27b866f2fe38b09d4
a262867f4782f15a5a0e762f76e1dae8062ba108e759c6d8f00ec4da4b4bff0e
3b22b22fdc733b708e0c8ed1acc316d8677e488adff3fd5d912fbee47a55e583
d814d6a77044767539c2a1b964f5a2522b482186ec9f957684f090862afac470
7e5b48722a97df0d272c713ba3b611aacdbaa0ed665ce873979c55cd6a9dac4f
b8aeca0b0cb0f6fe85e7c97088ac6f4ed2bce9a0d16527d001507702138709bc
abdb694a61da95692e67999aa628b73837f53ca6892788ac702cd6eb52f8c79b
92c866213a6126049797a48454b53318cfdebcbe1c50fd139abe01c30feec51f
0cb7e9d9a863250021dfe7c27786e88b6baedd48d949dc481684e3faf67ca81e
e76cfbd63b547d7a43f3ec9ad09b1bc9e31462a43245f40ee9f0cbe070805a1a
bf940f2ed8300be39fecb86120ec4b0e680d890903458cb93153fd2ed736b873
07aec4beb473ec4935bfb0b8c01ad84dac20d13b997a884930e3c6abdaabb083
f6f66c5b936ec4624fd1d1ca39011688ef21faff4f69b93f7fe73a7ae036c3d1
5f6f5da6838536f3fe0f7543f3f9460b197a7892d6424ba822cdcb26e2b3dd7c
a75ad2710b9ab49c6d5810f68d1a0426987f1e462034ddb4aea10e8e04be42ea
10cd8552670f9251994dd8e844245e97a5902b65d08fd41013de3f3cf0cd6dfe
c75852ec385747f789cb0d846d0d8f4f0c823fe8a6202101f2cdb1811cac9e71
9f54bffb04d646ebf824a17db7d78137f4e962f3fe6a19fec02697503d1f5c1a
467799d2c347e8f85395eb9bd63f4e6a52fa05d4a3e25700b4de22c41d97c719
cd5a7576a3dc797c96bf68c5ce7922a8fc928d6aa344fb67d4115cafa38e82f7
5f621c9153f7f2f9e5ab5817e000d5eba9a789eae7831e1a75a382c6181a130b
0ae6aac0e5cec25c567f1c3eb72caeba74fcd4ab5da3b73412e76399a56533ca
6044f2c2df96153ea47213cdc057e3cdfc8923b80543e5c5b226628dc0bece91
e30fafeb8d4a860c90021c1a996d178c6c85e9be45f28edd3fba26d6ef2e486c
477670a17494c453ff09074c083aa8b74de9493f207b555c56e72fdb8867ccac
10f060675e0393d1e5c6b2f44f08458dfa45cd4bdddc3ce3aeb5c7afaa73086c
c7399ec8874f529e4af63bcb4df147edda137e552ca22f45ff9fa03ac41f724b
870d8656fd9bb93690eeb0e7df81e6957e602a0159ebf6692fadbc46c9ded8ec
229d9bb5cb617518127e557671723dd8768b1ee594ec29c4a096ec4fe6192ec5
038eea033d0894c70de3920d1deac65b4fb001ed0c851779ed7154ef5a848257
c973c7f02aa72c1067dd09b13575a33d3137969d683ebd38e8b61cf62fd3f4e3
ce98c266e088aef330d9acb450ebbf96bf63600e83f13152eb0353801d2fca3e
18eef4f1fd438afe54026028dfd703cfce0bca12b0d2fdba236918d27517393d
c2ebd744f78e3dec0ce74805418f1a93252abef1ad71acc1809460a8dc423800
86a593b8167212ad7ee18288d203244dd3a2025b8449c47021ff7620fb89d3ed
41f8547bd5328e7ac7cf5f0ebfc314bd4afa8323d0cba57e98058af91ff4002e
db452461e95eb2bff94e464bed868dc3014915a910704c5740a1ffe4eb3caffe
27c199f573a2b8310ef7dca5dd1baaee4eb5add21887d9b65246d93e36a72766
e664b83245aea45114ca3c11b50d51d218eddd1fdade2aeabd385ce371734446
745552c5322e029c892e227dcb3fd626cccdbb1731d4cd23057686833fc20906
fb3640b2481fdadf09ee20e487556f5dafb429d648d74f57c8f6aa04f2ef121d
f2fd850667df1668f97d721647207084840861f2627f31e8858bfe5851c35fdb
b4a81e41645ceac4873fd2447ff94ebe8b83636578eaed2be03bd8f283fb6832
c10a917d9ad056ac7ce149186b5664cc52cab3939ef44f35b43bf33cf06416fd
ff848179580a7c39732e7eeffce44f7b24cfb288534f47163a273f2a5d9f30ae
802af8ca1dd90bb7149e3c3a3082fa471257bff78019380b1ac8238b735666c2
df052ea0b436789bee7ad5dd407e9c20774d5ff3e0af9187e24065dc9a119cb8
842c5f37421d005f27d787a611a8f52ce76aa34ee0ac7236905c28d6d9841415
387be7eca5c533ef618397c89f3df4cb86ea2e38ec497e380efd12743f6bc297
629e86fd88cc269eaadd0dd63984e253caa270ac816df54077f7981cf1f1d5a7
7aa46b7538794d9d414db7f7eda8831fd123f843b4b6a963648b2f3169693292
6626e040cda63af93f25d4a6e304d3b05c171c7186f5ba239f9e2156a0e9d30f
d016aafff969eecff0111120c07706f09505359f63199c3e19e8142bc84b7efc
caa61b1f13828755bf18cab9eb638f17c3f20342f60c1e1850332c16c8d21c26
40dbb93652c7cc6469486584f2e036160ed2334c5cbf3b343c9c20fb460fe049
2ac14315bbe89139796ad76f219f2f78aa252aba529db54863fba815857b4369
dbf510ecf4db2255912af8fb0a1d7c1a2d176fbfbbff0182b969c8b02780868d
2267b49d78b449702c46d1267319d79a101cabf6afef50a912b2fcb8482539e4
9e919f3b1270599e8ccd1becd4fc4b973bf1d412764dcc3013c707039fc5db85
b8c4759f7fb9be1fd2fc5d972e117af55ef2586b4441a440f350840210186a5e
d1e4019761f7b460cebf431c6d564322cc22362d93433f843166133fdcd079db
0f03591ae83885345c227b918e762e71db2b5e86653898d20f80c18c7f811797
cd7f4a0b3c6c5d3289c5fe808a7068f3d19e8c4ae145fb822d59d2344bd47dd5
6fc4f2c7237119a44710846bae73c9d13db5f08114ae8fbf644831e81dec6206
d933c007f15c0c0ca65091a451a3f4268529df3d047f8c04bfbd7d7bc02b76fd
3aaf76991f6f0b2b4b6a4fb87dfb7281a260920f79aa6c0cd16bd15de94e8681
fc684280948d6279ca994a078a261860c868d0a029c70f80903265db27ed9791
2c5a80e648aa078a321e5cb431c0bb2a9d21e9929a4ff4b1f9dbe980bf7ae713
f76ba86fd6dfc798d7488b115e7c30d1068322010037fc6c9bcc6182df29c66b
2477dc0197f1ec7f48a7473b80a284d917378e89b79c9aef1e975fc3edc7c60b
a3afdace73264dd561ad9478a3cbbf9858978620c79c09d660b1048d3ff8044d
c2bf02d1282e396f5c6298c30f3116285c16d3262630330c4fea515f629d480b
cbaaaeba211aabcb932c2c8c9cbb2d48092f69f11c221d9ca068c529213b4303
e7db0af9ea0ecefa45fdcfa5478312aeee4e7ab6d393b8b578cc181bde18d138
6eee5ecb8aa46d9c62eb8dac91fc3375f93917170a43c2fb48ec5bf00d15c5fc
f1d55710b6801ba04b406ad183dff76e19ee9526e6c38d5c2b084e8f36b7a9b1
68ff8d2027c20b0d79d120a0785a35f93ac1f2a7319c65e68a4abbfd0ee8a3e9
b14b3c5f230482032323b501a82424aa3256af1f7b5de145b16848b9bdb70bcc
c4f83c231aae58de03afd4b7d0c7cadadff17b2dbe285300606de214cef1c624
1d2f2969f0b9741dc34d8dfdd30331d8fb2b12d3bffc004ad1e9bccaf126e96a
5e340a89e8a91a9eb19ea03d4886f768ce063c702f25f5ccc8f473f3a4b85fad
95d7a92d2e3318f635bbd79a8a4eee3f1208e9e69a7d63de373262d38eb8ac61
21f3df1bba843a961b5d3e7f8735ff641ea99fefd347df900b678758080fe745
538c9d5ad428839bb6840d084a49b2cc475319a99b33a178a4b4f24e56a9c251
9e8c010f81de925cb895a446c87b63ecea312c8b230151adf735c6b7b158a1d6
55e44e2f5c77c2b461b97e494dd098fdea07d1940427d2a3f2585abf264bc4ed
efada3790a85e0889e90e45c38482909b802b8c4c678e1129af4382e479e49a9
e406e7120b85955936ffd8a40f41e91238e4d11c7e660b902897e9746f9948ec
29ed59c91597ab7d2137149edc67bc432e470a404bb9e6b1f98bcfdf1d49389f
828e3f35c203a3aededd8d4d3e6617c959d5c401fae6756223f2ff5b52134cc2
804d20bb08498b8d00b0660fd27b4511a9a099a8487b7622184d781b47453611
484da293aaa6b7e8124785991f755bbf689c4cd86e573f40e4f9cce9ffb6c5a8
4a419e32002acd3392e677cdc2883bddc975bf0550a41e7d5623d745f389fab0
5918c7cdfc9f49327eb8c4a59fad6ba52b0f075fe0a2851fde85910cf5cc9590
b7d7bea3a1a8a251e37f6a20205b946b01da9adba76d14506850b6e634ddfdb3
c853739461d428ac3349438634bc2c4577fa2a337990eb7bec05a6d9b90cfe70
856680d5e822480f77f580c3a1e82b87dc2c2c554235da6133e79ad708786a8f
bfc34d813f4e4330afbd5e03f7ef0875a7a07aa201c7e71ab6a818afb9399ebf
d88e1d438e5d4634172f2f7000c10112692c4e9f0273a8db1c559b2e8d66fe93
521514d2896b7321372d441e1e7c63edc272b30b6735ae53ac1b08c352aced8e
8e569d3d3dc4e7b79c9a58310d03ac8d2760522cce13bb95bddbb22a13b13cfb
78bbbf43cbee6adfb333ea66621a5616442fb9eb4d5855eafb1573075650d05b
9b36e80e8ee6e5a4115aa1234ef0898c52ba94d85072c4da759dc246ae56ea52
6be02430ffa280c4052cf73d6eb4b62c3282d82929177263931d89f27b1e1dc8
de5ecabd3e348ae919c983913e6ea48b21bc0827807fba233c132aaf170f20b3
3ba72160f184a3df9b130e3bd09301e12d0b22dbf56ce6fc87ce156de4377498
cad735a6f5e57840ebd7706ee44c6b44a9bc0120cd4f50720ba4b4f4002e11db
98d7db9a31a5c300d81546ef990481b7f9c278f0853c05b0fe5ef2586b4441a4
218a64a07ed2bd6c547de31987297af9e99f16ecc361ec2650cbfc0ca9b55cb8
f5b11408d58fe29e46eb31a0537fe757800abd0f34398cef4e77362a140d3ef6
b00e83e143656b00cd218db158d44f5df1c5976fe708f15e32642e629645f1dc
1a3d22742637a809f2197ff9a60d1f58e74d0937f8d8cbf0b0de616809d91cfe
77675bc90ebd5cd44fc09ca0625e8cd6144b620bea2183744d33c42e535b4879
ee3fc032610eab99688a6e800815164ce529eab33e85cb2a84ca3cea8074039a
5b0b9e2065fd72389d02c6608660adcdd7ddeb2c4feb5a32e3276025f5c3ff65
bf4b01473897164745b05a4c1e1dbaeeb2506bd306e266e613b16b93ac0f869a
ecf140786a639f9856d2f47dfd448564cd6067590cd7c75bbe8b58eef67d2ea3
8c965e69c090c242e29f12dee8b4335b8ecf7ef341de3a30892c09ef87913cf5
147ae0cc255e05eb602420ae22e8c2754976dc6ce94fc477f330dba72728449d
459b2ecfecec62d0be91a9397b312a7d46b0cb7cfa2fc664397dbf9a50bcfbc6
3ed6fd6a7941d36a37a815cc9290c79fe24f19d1a5c1cf0671a73c6c22abb952
5618c9a3a9909f1850a9f470d2fde679c254bf516641ef96f46574633a94bd7e
c9890023100e55c6a51f1124b3dec6a7fd42f63499a1066d8d27a25819a7ca1a
979e04a8f1fa55d4aaa3eb05d8205cf93fe5d372778e809ba05dfb1e0a1e60ab
6d1140d4c0bd8e2db88e7d68eca8e3f3e2248cb6fcd2919c12d60bf4549cad35
6000877d0241f7f19487e8c2b17a522bac5a91f864630e2ea4d2f5b7bef4d091
064ed22d2f597d18c9f04e2e2e1be2ed884cafd31231da6133e79ad708400c02
fa56a3f3f5eb56a713fe068d4cf564e7e20dec5cd4696759cc35d34fc0efce5b
dda7c02eaad828006036386ca3432c6c005aee97bc884afccd3b642c0a17f418
e3f2e436dd02237531cf86ae391102b2023ae0913471b6797a8e71031412ac87
b96a7173d5a56332ddc5811f8672b377955fb5e39f90d787ed2b0cdb81866f79
165c8353c9cc1f0924b5f4ab6bd5197ea6273aed03c838f6a78bd9c40eb8b71b
436c0803bd569c3ae55ffac24dac9de63cf6f851c5e2199c11d9da77009e5531
09e47298f63c44644470d768725db00743efd4b012665664b3f663da65c6329d
a22e64b466f56bb45e7afa47e1d2e8680a49fb4948a8c424c175ebb3f221a458
d75f3f84929ba4716c503c81e9baf81999337a0e74d9c386e2b46aa7ecaa0689
e5b00465cc49f96f7003d7d0bd1463372602a5a18bdf3e924493566ee07b37df
97814292f85845f2cdae528cf8e6d40b1b4c7ab83c276f3d9712e7cd00e96f81
39dee7bc8d17b48a57a39210ae727a8563319091fb1944279c1e670a24093b0d
03ac8d4a479d2eead32e98af57251eaef7a6a110493471c97c04cb50fed0461d
b5d0f89df4f461b67bf479fac30463af0eb0a5c40b3ada200bda798ca929d04c
aca634d46b3fcfc12980c2ece9439363ee588b4cfbfe1adf3520a28209e59572
148f5dd6e4891d9bdfb2525b5d4e16fb79c13a65e1d6872b1e2ef1c761d1ba66
ea1ca508c2a3bb27a32515269ed4377d1ee7ddc8c94c4078bc4b352211cea134
95326faf27554edfc3a8854cdd4ed995df19dedd2beaa478a9409a77f75fc1f4
d57ac4352afaface9ad01b0b621cd8572b3c65878ea89e3f43269e8a0c3854c1
454418f7b0b385044a15ccc1823961ceac3f500a09579e605f92f0bbc9f2d816
8c50cd9e61b84e0fc17ad73c36227e22447b9ef1296f2fe302f23663deef0fc1
eb759acc9dd1909f369fca5564adb3f0b2ed33428c75fcea4caac27e7e2ebcb3
f50fe19f3a3904eb94baf40c40bfdf8a787e622563a2cbf6c32de0eb309ebbc4
402e31bcdce135d63f42f314928df9816b69e19f732539bd00b5950b5aa8fc6c
b3bec0f14e60c3b97423680fd8158fae9b076f3d25aa3fd81bb5132f9b1f150a
caf2cbc0744e0d4f42b186af0591f16f51eca0ab48aa2525dbbf629b4754f235
49f1f9a88d2ec444c26f28ad54c9c388ed9c00c9b2f5a19a32fb8880c47ebb80
16ceb36d0cc17489b3e4e552984ff17ec5388f14541759ec95282eaeb4a2d6e3
192cebedc3526f99363024cdebb040b3da29dc93b58f6090f2f5bac6c67c8ea4
88b3f0eff0d6228e20a5b865bb2d1870e9e76c9663fb32e899c3f1f03507e174
af0e77433fb35748aba9dc78f419fab7c9e508f73824460a7fe6ee23fca964a2
839043a19ecb24b15b6406769b703a3b831bd6c4c82ee4af7aad7e5295f85353
c7d3476119fc664568089a3350ca986913f16002e2889a7f091e02e3a400cf8b
83ece85176f96fc41efa93d5d658f45ac91e6e566184cc0376ebc6c8491f09c5
e6b12eeea7e4e445a8821e03a381c468bdef4f7074b631a3146675b53f7539b2
11e0b3b1885eb173883c4cacf1223ef4f6dcaed8054c8738fc3dd1abf1566be3
b4d8e99bc538504742ab18cb9e5cf97c9e5284aba6f591e2d87f00952d0388ba
ee7c3ba1182073481edc7b9c0e761a85a1643941fc9a0bb39252d59c5b0abad3
85ca9296546fdb9faf2bd384db91bd96c59da8250df2b5d125d0b2546bc7e2c5
0ed4dc568d8f1b65b6f327842bed0e7e910e44ddfa302f5b30ec127aef3f02f1
1dc0ce8a94bd9a77c33c8e366ad06f6675806d7f4e77282f88376fcc8e1772e4
1ee7f1e9cde177b826f9069ed5c3d3d0b4bd54bd60e01d4c768cb47b27624853
fd9e3760387debdb46d9dfb6da0f7afc1e1ca352f141b9039c6d2f3ee7ba88db
d5f1a0db0753962fad600b9245a3a6bdb0bc0dae1e65c3b27bf95a52353bff9d
34d860a5d9de8ea0547b9100c160b7b631ef5d8e2bdae77d7a915788bef9eb91
11d4d7f60f0329462d2ea14a7da9289922a575fd88a52c1aa98cf1f4f34b7054
64336e3ab7cb09d81e427e3bf24e87bf7147dfc0c52e6c67205181ad234ca1ff
0dedd467d4a13bf9afdc6167bb6f33a47f1ab1477ab32752c256286b25438259
a143a6d95b2c6e5dd38dca03fd6c803782dd7dab0c7c0647f48a84a163cfec2c
e098a2ee99d2b0d46e0afc85091c8402b36b41cc096e733d3e7252c2a4b58f54
369f049d0924a6903f8ad3e1bbea39e25bfa05815f79eef03e1748b2d581fe11
7ab2e3c7a8f520c194b3c5e98fdea58f19b4e79d677ad54a7fa485a7a9712896
618b0c33694a3c3467a245c52cd39fe9730e7c2634d298c1638a0c7109692cf2
58f8a6d0bdf578cd28f72e48176a959993014e050a7d060918fde0a223eab193
96cca9c895a0d5bb26eeeb9190df3f07e2d6243d7a845404be35983125b133d3
7bf15f8c7cffc8ecf514969e23fabd262facea11fee56fa69682307719c216b7
881b733d24403eb703c288cbf898749f3e81fe24451e063b3c02cb2ef8dcfc36
179a525662d47e0e6325b93d885973935c91cc6c52749a939d32fa1f5a74b689
d06d161914dffba8335c544ad8c4e83522f403157b7aa2ab15593a7583c684e4
72df545d24a4894038195781caa9f0f49a66fc62fbd0a5155743b7c17c9e6ffa
e86076684c20a77b1e74abf75aab577b93dcde8c3ff60aed1a87ec006d276725
215681e444c21acbb6318f41d175894c303738994c15099f4021950a8b389dc2
ab91b74ed57317f7faf10f00bda6be25467f05676ac4192c369ce03bb374617a
d5bebcc56ffc07cb5d8e7da3e17b7ab3d9d5dba4b8354c03a64f02be62ef5df1
4b9b9376e79a803423bc55c5cee3972f75faf61dc41d1e8415ca55d3cf703612
1cfe771be80b697389c047c601dbb8548f0d58ed841d25531a41d8664730f34e
2b187bbeb8d9c16ae7591ca61fb2ab36ff3b6782c7e97833827a1ff86644ae56
f463956635883b55891a08fa707e90c392ae4721fdb0b2311f8cf00a4703faad
8114b615eef9737684a3c53ca307abd11558ce0810db4d94a444fc6babbbe40f
3fca201d7f66ed5f834d33eeb1189648d68efefb7af5a080f1b6297b75e7815b
4680e3c4b2676f3c763fd9d28fd00374c2ff2697bb8b96ea13cebdf68eb17001
c041d24e19c97d33d448f4d6aa3d50d8720b0377135f30b479d973ebebb93031
aa1faee6c275b21cd88852d903f08e2629066e18bfcdfe736b208429a99f7420
7fe3f156e82b16cbe3d401aaf8ea2a417a7ded77fc22d8f047685fb642b7e25a
50c5141c1f1f38a14ce3c0b8b3447d8f48de07c687e4c4cf69204e85c6489a3c
adf29ca7f2363308621dfd1f48efe47d7fcb3f67441ce965f04f42b78d23500d
25890201f30d13dc767cebd955da0ce6f6411001fac35b8ff9762eeafda44864
cf1fd2f8c5c006ae8afaea913ae1c75765e4d6d77b7e21a6d16daac81366f237
78d2c5b9a64872015bbad846c77d4a9b93353935d2b6e57b39ebbb02993c18f5
228d99a76250b85311629162556dd299f7eb2479c705c6e477167faec90ace94
4145a22a5cdca376cd2f809ee685329d8ae45f3d29b2187bd4077b1e7c5889aa
d999a67759f2b649e82031f198bc592bff385a196f4b9943300e1c9557ccad85
497b9f2c5ac963b85527302a1d7c42d5d5c8c58328318a6410df0437225eb017
494c3aa09f129275a02d0f0d2d5e24fa35a6b0112435d63cc0706491cdb6e75d
d957789831d30481e3b8e52d678d0990202a4310255adefea4a4b48abf4b835d
35c66f7f279e1d7cd4887798ef065d2218056e2374c03c99fc2e17a24a9e70b4
9440f5e20c8806dc23e1b1b545716dcea57adc5e40d7df2a7a259b559cd37c2d
8fb1eeb6731601ccb46af23de0ba8c1628f4b88a9b2d468c96730bff946e66a5
d200ae32702e6fa6c907ca03518731f60b1252a5cc2dd1f9bd90428c2e0f0a7c
54d92afc89333da6a83c324af0629a26996457d6374437d9cef97bb99eff0e98
a22c6b0deba1062f3c48226dbc9a5899cc864b975bd1f082d7e511a5b4cf9c0d
7f30d371f689da42f11df7c18389941337b9c07e1cf5f5cbf33e400feb6f4aae
e60a026da25d51a3bc14d427d37fbc1e64e938a4de50f52578768bc70ce53327
2db34369f898761aec2c8dda5931f895d28872ec6f209d78be4f4ab8da35f656
97c57405ce7ae5541c9ff509d5762aa6297e7a0194059eef3a2ae5d59dfad4e9
807cba47217ba163742c83f8205052cd729ed6f8c452af9712dee557d4bf8a30
3209d36bdddb790812c4e532165f955c981339226c4ccdb89f78666953c02eb2
f38c4cacff62da858e16feb7bd379b92d9420a26fe2a0aa0c71e064000164413
7c538d2da78a5403cae324705be07519a4c6124f4e299c41497f23ab3c479ac8
e309dc694cb84b693a40ef5fa7d4eaeb84e97643474253f982e38060a81ef3de
b08144992e048e8fe2e9719ee6c840e5be01142f4a62ff3f2f1b1d70997f1fcd
183c5cdc04d67e5f46f946eefd6abbcf0170141516c7bffc2a07efb440dce1ce
888a5acbe4c407c8fa46e28d20e7774d2e374e224b991242df5a20cf3be574c4
10a1a88badb054b812e7f3ea575682e6a86792ff4ea12bb43245bfdf588df7ce
ae590954e88607c4201efb34b2a9cffaaa392ab52f72ec08de1424d2420bf7b8
2f2a0dc2aa083310b4a6f2a68ab5ee8384bbbf4ed9f932308c2836d6de8da231
dee2b4f08790d1653490b71ad5d0bed41b06f659f8c3a771b82c8e58ec4e0a0c
5a9f7f9874bc6a1479b918050f06e4d1b49232d8b44f312a5f6666b49e54389c
18e7d89a399fac13ea6ea584dd48ac68c0ee40d26e4f2ac32951a3aef14c503c
7ca2d05701b756990b9809e25384b0815fe2bf5084ed21d8cdab1fe3cbe15c41
e8a94336359df9ed3a43c529529a9e7f63d8de36720e108d1a9feb0b9ec91379
b57d2ac8a6799176ca5d5956ab877d87050d86ab917689c93652b729d4746f6f
34de32680d8ab5c5a4565512d6ec950a60f5b0b141f348d1934b4f3689640592
f22d1c1cbcdd5116b204061afc1b8f15afcb06f4c44905d17b8e44ec96ca2888
b34eb85465ed2b2620756ed963fbb9312883c8aaf4870c52eb032bb5cb7458b2
fbd796b670e972f576dd3941c76cbed5c40b669f0dcb34b31d29501097553698
9bd2a479acfcf324fd549b3e41bdefd06f42492c36d8c0201d2526e53ad34e55
2b2384e39836743766e384e5858f33ac842cfedc28022ee8dbefb2a2c3a408a6
be84826023124f7eec8295a2e1079480f30eb64479f2673da8f051267142dc54
e88dc8dc4ef41036f1de1b9a198e5006f8336b29720288c9f2e545ec8663171a
280273b1626f882c6894be2fa2532c2f20e4e24f1406c0627f9cc4021cac67c8
3a60b39f1849b483757f18ca956ec3bbaea96cb0e2a10477e69a6040dc3b5321
391af5478fdded8730e825818d960c6f4a305d653a732f1c51c2ca3e3adc4a37
22958d50a78359cabcffaae1d75ce79e72e09a354c5e805967e30ae708c109ee
75ef233df66782bebc4c5dd9ed6ef0a50eb2693787576a19b42e70e3d0c073fd
fe1b3562083bc01d9b38868e64b8ae90b9f3164e2a29fbb1f1bdfd8ffc2a842a
c2f9801d4839c97f4bdaf1466038eb4b6975e777acbdd875beb59268f0eae6d3
a03c2bb60bda0ffaaf77c4f33d4671ee85f301521557a6f323f1b0d060326fd8
7c60f65e4220b7fdf85de8f0ed64661fddba2efd3374fc45a507437a1ad2ab49
38e4ccbe2411ffb70718397e156d24ab018436fecd39af252f3f9527397cdab6
75b261045194cb3d3b5aca47c98f1177ca1322775aa8c29216fb7f8ce0fbe698
479abd173b9541fdebbc3cde6ad12be816108a049d5462572544912ecac19e6e
9fc6dc06160904e7bb14796e5becff4df3a8f645825c9f59fb419bfb5ced8e5b
449a2e57adc9693e9d34e6bb5a600d16189bf146f3dbaf4f75d16b303a322048
ddc0de4a91156aa427f1b137a714f7ec2a4aaf612de4819dede79b78c90a86c9
01278125bf2999c9acfd90a866830d00a0f1c83a87cec69cb2f382c935bc571e
a3b53fb22664be95d8e95d229b9985d992dbc6439f0ca52762b3cd7a4a50973c
17de473f987151687da95caf1457c524a4406c98bd025f353124da7e6389a921
e56de4d1ca7901cb37f051b9d3b78709640530cd549c9907ee6def35aeb2eecd
1c9a1a4ae7686da61b848371dcacd9f02cc320f29ef144a10803df5dc4621887
09a85504074b8439c1a3a7c253581597d6f94289e7113c678fae406b6586ec40
fe51769903be72259817704579212bbe802679ef21f7578fae78d1f8c29a5438
b656f13d14ac4b10d1b48d83dd1ec6e569358f9dce2093f319f9d3663e331744
bca142ec6b901acb9b5594ea7423072d96a61e523336059c1091823b03dc6756
71cfc688bd2062830e0edf7a5d400c680784691ff46bf4d8853a42c57320414a
0c7b838bf2bc33726d8a61d11dc42005b909b241b553c37462ba057c30e7bdee
b3ec5513ddca5046dbf783c780ffccdc188b5890daf03c94c8bbeadd2e33e95a
8bad7cf8c890753d607e1e74dda3963d32cd37ad2d0eb722498718df3827236d
7f073eed7fc3c0ce0fb5629f08d4a71d1825c4d158ef364c8d69e8767acbaa92
e1751a266718d67fb61b4a07c485cb887f04bd30468bd6ff5163e5e35c7b4bf6
ead5db27d8690d7c54b2be107d8180396ba6046e8b1ec7f51a624a52ad2f9e25
96df52d886aa0f5f0316fb0a6ff881ef3cf2a11debba86921f94b6ab18088a61
ccb125c7732c3681373e4151094543ad56ba6b5b915ca303a753a65aa189f6d7
1bcd8ab565ab5696b9b0a2fb5b7feef3dcd6ef83f859fa4be52c24c31ec71153
4577aba733b4f0ec2ca742f8bd658d7646e6af057d09b504f072b85e8ce75c51
cdb3b17d34c06c1ca57b88e7ae944d289bcbc1f7ad27898a703c0b2b9e0dfc9f
87a6b2c1d9ea2cc05fef8bffb8cffd8d8246ddc86e135a8361d36748680881d2
5daeefbe63d60e449d50acc1718f1b6df6297849d31eecb6c990304d5e37d6bc
d83c17c4ebded22db52466af31cdd0b576d69ed50ef359cb44507a79462b2825
04a48a4b8bbe2ef617837ae266e3ab90e5f45647ed6b99c6d8b6121f1f7771f7
5b76362f01bbe8a8b4268d4755c7b613b2faed3f108c29bda855012eea6c2221
0f618b416e25534efec4c0f6d0feaa4ce7517802f2ccf54c96c4b5b9227bb59f
8c8a49fb435d4134dce397f41f3b6d295f6453b9483c3c1d2ffd47a3199b370f
2f31b3772afd59d0135ee2970b66acc4a1a0d3a18be2b3cc0a8a261e9dfe32b1
a63ebc7fd99af94cabd34eeafca393ab83b5ced9b4e60f868e0b7aad2c2f21b0
d84919f1c1598e6143440481e3c4a97750300f7e0660eb65416215d13d8f546f
74c4700693327ae762ef61db4463f3644d534a3b4127c06741f0f3394f395ed3
84c4139b7ffc5b02185dd9e9fc4a9a790d91eda97f8262e6327779701f7440a2
7120c75242cb2e3c5570399c648b21da288d2a9d610dd11d5f9cfae9aa1caf9f
05437bc137d8cf0e83272ecdec1c574ee6880505f03fb673c5ef5e31a674d1fa
390de77900b9dc1fe4d73311032af31f6985bf38005fd3498d569de012062aa9
c4e5baee3ee651230cf8f06f9562482e56aef639b4e9b14fe104d7a4e59d9f59
ed573a530fead02933ab576a225e00d4681821a6bd294b96c9f73ead9eba509a
e5d9008007ece9e52dbe377e161c5b5e1fe556db12e167595ca9024a24c72e65
527e3f4b94353bc5fd302dcd2343dfc038950bbc4c1249776e2561a90c9a5ca9
c045f6812d9491a77d5f775ccaf51b81f299e1f9122c50712fcd660bf649f628
2aee3c072d41bfb68cc3aec648f2201fd414d50e1375dc1fa058a80f54ef4852
2715a66f46b0da8861864fdf8e22f6e47cb32837b34ffdc5b578717a1119c6e7
ef7566c58b373d111eb6c2bf1e9853d13c6223fac9ad3123765163c06dfc0637
c692af835e89ebecf5b37620104cb8f17851abfa357e02703a059d960d9df6f7
fdbb168337708e7f919c04c802ea2e2b3a3babf74eb86e63de9b8644627d8985
a1ad3b8adcca509f7a7debdd4634cbf42715063265b57d40eb7475423c383835
9cb5a1fccfcc7874c782cd859ba71d5f114991e6fe5e557fd360943786fa1610
75b6783140ef30382f184be07a3b0bb616442a4a4007af227492a994854b4029
8b9e9b4e4483dd252b2230f1f615a122918f32c3ea0a68805fcc73bca40be7f3
fd94e698d0a65005a64dcbb7d97f60cab183acc86762873f18b673dc194cfce1
03f07cad09c8fd6b1f532d72cc86ea99ea24a21a41a2e09837093d5e1f1e3d74
342cc4466d9ed9c1722d8665b00a9f254950c286426737b8690914d856ac20f1
bf27180e6f9b00981bc8b3b165c5cc7e02a689dccfd58c1b5939186c590a97d0
4d5710fb5506bcfff05f8c6241c125e300235afcd2311d997a1369783a83ee1f
040b8fe44804dd62ff7e5e77dbfd66177a934eaee33737d643092a0cf65e51b1
31a7ce8e502102aba1a8a68b8d95c5b0651c83214017ea2bd5e5a52d7e9d8afb
ba7cd22bbcaae087ead54739401b0d8acda7766d94d640feecca18f1829ae75d
a4aba8485bc9dfc9c67409c7d465f54d740ccc8ed6452872082bea2773fd5d64
6a809f5d382b69955db3a56e61849017f103bec6de80850132002216dfd30111
0250985d8241933cab0ceac16e90d929dda1d3169a8de16ca98aeec1bf59b9b4
e0ec460a2631f6d3ad4f84fde5b5dcd29d53afbc6c8a3adf15d234b13de3fce5
2689a74f49cdf2d9affd89a098d6fa7c0f93724a08324ed1ce7db85034bf4a67
e7d0573db8e2fbd09e123156b2d066bccd9db05b87cf61545a6e219009452b75
41aba3802cade07019910ced99eccd026725d0853f9f159703f449d1e1d33902
148421d34f132378dd12d9e79168bcd8dec5bfe47c862adbf7883e46dcf0c241
e068ca77b72ce9a73a3ac40f568481f62d9f36ede5f0264c4d8f9b2ce03e19e7
0a94d0e467a9832efbacffcff9efbcbd405432914bc36fcbd16c4c2aba631f82
13239b69f183482bd2922470427fbab78cc598a57819dae5e3321efef1fdb44e
084a4402b8cee480242e42dc09bbf208042dea7968a643851cac21aebc1ba274
0ac999d965b43feaedc8c76a32ff8d4fa30e2c8444b01716af4878ecf291309c
bdb70c5bfbd4134ad5d044a04a057405a91e1a1ef15980383cd4aadd4190904d
5528e55138635714ec3f9d8e0fe1bd1e8ed4b742ea90572f1ac8d01e711c074a
4125ea595fbce0746121a5d022d16b2125a1577850f6d1010279a5dbbf135eb8
edcdcfc459b7b554192149c29327f86e477dd3d13fa5ae3a78cfb714c9a75006
7ba154407ef22158670059820c8041941f7ff5c27c016b20b867f83a9c8955dc
d282dbb6f72bd2067dfc1e91373a3021be2be6aec5f90c8001878077eabc9263
9f5beb892bfded1d04136bb3140dafaeeeb31c21d8baf03715fc56ecc16e7dd1
1c12df0bb68240772f2c59829482cf97f6a922c8c7deccd1a395e7ba2a1a8552
06c27630ae1f236606a3a9dba1404326b8b484d5d2564b480ee7422365234cef
2609605ad9e24294ce5f5bdd61a479c33fe53ee8bf857e2d2a25dbbc9a1cfad3
a5d7b2f1155d29367e318c8a82e1e0aa236b8442838e3deeb9f7455923cd769d
28c1f780c0d3bffc275e0242ec975d2beb7f6bb5222b2cdd196e4ec94452050a
76a4aa6352633cd58f461fd646f23758e343b5a386927b66ac6ef1acc84839f8
bcca9f9f93f18cb4c6bbc663a951dd5211acd684ef945c10f156b5b6e1c182a7
a580b3966716c334ddd9f78a404873a738ab6ccf8a335f1f6dc830d7d74e021b
bca95d260b34d1933177e5ead9c2793d264c94e8bb274b9712afb7862bbd8f74
b4cce27cac9f29c086bb30162820a229e6d5c83410a8b876fad5b8a028abc067
885b5cec60995550d35f60afd1da93e3dc14c42decd2b0800706a222e9e4b7d7
bba9646f6a3ef9489dfb011045a6444cb599c62dcae4b11de7d8d98f8e58a9a4
feba0e5f7301b795f4085baa4a7085c5a438d0b784b21186787abf88b455f1e2
ef19fbbb4501d5c69c22b219737aa5ceca0d0475bb6916685534448816d2791a
31544769ff1152c2f2cf4c7cd3f64c6830522219349254d11e6ff2056a341648
e9caf2fc5c6f48a8713448b4a0a7bf4f250df1f9ab9db798e0c5d2cad0116608
a0a6190d8fa4f8e67f705d8dfc7cd8be652b13ec24beb159f97d22997094e38e
90fe6e9f3d2a07ac92f1648c78e6ca7452481fb78dfefdb4399c62986b652e08
ca4a9a4966cbbb572c4b2c8bedb9285372904836abcea90e91ee6fe8dbe8fcf7
18f4e0ce97b29be634db1f19b541e003409442a59e320cd38789b76eb79e35ac
b1e09f5ac2eee068664a0f505c61c07da5bbf439acd52feb4caac79ff0575647
2aada68f6aad5a1b760468859d9297e3ac4ceaf7830c09d3562c012d48cf7da5
f93d7942a15fd76be4e90cb1a966503d32dd2fc39c1cd01c629b600ba6463288
466ebf44a4df63fe204067d6a39719ab32b5073d4bdd022933b5bb5652510919
af2f90863be9f08dc507609487ebd7b796a3f0b029e13492cd0a1dc002d85b8d
a0d2ddf319f7e732ed40a87c984340976292119ab947b5f5b9e5e31e6023e22e
6ef0d04bb9d9cbb7de56a1626c5925847300a6dbeed495b18deeb81580701052
e4b37d9e0b346aa8a55621bf5dfe3bd1cbf2051e62ab1e1da21387b5f38c1199
34ffab0e8158107bc33f36a537996faf01870b85d5da02977ba62fb8e5d4878e
1be660a6414c9084a3a5f05a4a2c3c1f311a589ba7afc5418e3b480c92f91033
ea61d0a6a1f9e209226f2cab2d9c10e2b54f22e9a730ab8d48548cd28c3dab41
5b03a59345bdfa9656cbdf48363eb233dead8ed309268a629bbc3c6e2d85eab1
5f3b769afef377e4602fee3efe33401eba124aa4d4593c5356214c59db31702f
44d33f89196e09e6e2215687c448c9615c69d7163b2867252de9771c9ee8a395
87bb374d1b705d61c42da4a8a7ed8ebd24d1062d377fb37fd84d5ec3eac25d5d
39bdc91f7c820b9fe806984bcfd3c3753a607650a6ee4460a24906f75b38f2c4
42a65909bb70e7383f9e90a06f13fa2acf0a37e59a31185b6f9437e741571dbe
fb518dd564140aab4c91d37e6435ab9b2b376bf6522f90b5660ccd1d7e8b82dc
3a41d34e2c39cdfa05f1e4a7ebdd3586e69c6ccc4847e086052dc7d6cd4d8302
c34f4f0402daf9549bdd83c24c44a68cc2e0c2635686c6e49ed8bd5675749650
a79e40588f4315fdb9c187fa7b4956151b7123f36937b06fd147eb8d51a8eeac
5461441d24afbadc7922cfc237823efff1a3e742b336e84702189c648ab7078d
6097d8fd5f3baec947d63912156478662aeda72a501c747a325d1227cd4093ff
e9a931367dde46d65857290ade9dc3d8eb73e7149dacc34c08faa51f9fa39e0c
13d14be58999496dfde61566e68f83135a0e43cab3cc6395217a0845423210cb
032c63d56bae68773991e91f186b198105f165723e08f6db39e889ef3f944d33
9886c0c6ed8e41c20c0743864a50d37c281abf47fba6d08728aa21a833f22aea
d0bc38d211caf58d44d01e10c2da4065a3082e562e82e3f1def28b5fbab1e93c
c3716256b98ce87e4dde9e93622e5ddce60981e89ad0d70d0fa8b1638f4c12ee
82a601073f84ccd47b631781ef34da22b5cd35023f23c6fff02973f993d7457e
fe579da64d7110867d6fabe6b41b97e9e711369232f98cac9975d56d69cfc985
30e76ecfa380311854170f98cc43596a3d4019d08c25e59dbc3eb850e026cd48
4644353c125e38f199b22ccf0a502d675d5e0be2a4df28ea88c3ca6b939b4b19
e81ab728d3e44648830f0ccaac81f705d098c127f07f56ca8550ceb827722d04
6ce419a2504d8d6740cf9ccb5d079f1086dff76bcef4bd20e854eed00bce0858
522818c8ebae755857d51961a9c61ab5367445b621562c645664f6df9f63a212
46ca26d21aeb97ab2b271003d5734719358b16d2af5cbc1799c88b899e3c964c
453e53de23d02bd3137cc0c1f07470d8ffea99d6a27e835ac56c977c149dfd13
de3c0c328f8edd67c1f95953b9892e0147a245ee0d4e5912c7eba0b810c0667b
17b545543b0662d53be35c26192356522fd7db85df65e5db4d6573b6c0c0f5da
3747e6fd6c4a041525f7e48b56ae420995938a2229c967e98c8256c28f3a99b0
739f75f0f1d250db34ecd7abcf25b86e6b94de40d033d99710fa654fafc2adf0
118f750a07aea2c94f205cbd091eb2a3bbbff77253122f179395e088c6b7a9f0
6ad421055622a1cc0538e8b3f03c4dec14746a49b2a19bb161ef7d5da64a4562
e3a0ad91e4ad5a052d74c1473febc4f186cd6b73d48a895e8bbba44657d00663
d5e76686f65a7ddc45ab8194be9fcd289e170994d8f17d4847080ec3f0fc36f8
11035bde3970e330f1b654034faf87b01b9981330b3513c2f32e13a280b52c92
449525bd879f684edc107a40c02da468ede54c9bf7ae72d4c314563e55d9d194
96d0f80472b2f3c8398700bee642314f87fcee7e0fb9e4500fc980e0a9f755c7
1cd9afe4b3946aa06d2ae458ea77080c3308f65bfa253674be7182dea45a8d2c
029a570cb3914f7c7cd0cf31f9b537b4f2f7cf918c5e82c6ab36f65ac444ce93
5e1d14f413c2c005ce388ef8175d7c8e7bfd68640c650385b646fd00dbdfbb9e
0ec83d93f7ddd486a358a8493a4327d11568d3145b52cfbd0bd5b4d7def67990
6fe1297a16908e16b9de0a13986d5ebf4f829c4de8eeab729480c1372c0b85c4
62d02d8e6bb0c45fb26e4d82f0152eea9b745e1c20e478ea50110efdc5bf0164
a678ecf71278fb2bf0c8a53a99ec0f46029eaff9229108234fa1624b5e33f927
2a232f64acd955839b942f8f8cd3f3e3871a443f685149bc5ad0083f6baf20c1
4025309173788aab5568160b31e7f7ab6f10f4033345656fe958613d626e8ab7
091aae62e2150d7f854d5740f601c0756b4d04a2f4ced1f833042b4ea609a051
defe8aed847795cacc657c5dde3331323d5f21b24154b3b2c991e3da5de77d00
a4577ccc862f035c10f2c073f85b97fb489a5d5a17d84d9ca133a018a22788ef
86afd7c1c8952eadc6cf5139605b19df95546e90a839440d56ea29625d57eba8
0472486cae74bd099198ab8619cbb6fcd652774b0a97806f5f83f6e8a109eeca
85cc7bfd19ae0cf27336e00d98d130f932be9752cbb97a14a44fc6407b286744
ff893a26ede2d28c6d5a2c2369388cd6a23bf8e102d7014b3944afea96cbe037
35db0e6e4922d4c5b2b6add56d317f3532fc50a410cf19be859075abe70ed195
996f9b9afc7b1f3b1a5d1602fc6d55d5171ccc345e28040625e4fabb28699011
6ff9dfdbbbd193d503d5ff027b0f4a3b124f2e0a1e428379ac6fecfa313fd135
a6f38da32b37b3d6b877e5148b55aa40567b78d69bfc59681acf8c871507eb03
518650eeac7270883e7003ab9ca8a2e531516c309c31f67a059349b0f603f584
c6d91770ded8a825c6f759cb3128bb928cb1e671c1684cfa153a41e6e775ebdf
54f25d11865ad5972e8bf3193fa4044fa618bfb88b621420c86a5a30b4716fea
a63197c6081bb1f324605d018e8c63753fab6f972670cbaa9a4946b9c20fa42c
6e52c9751654a3cd885fd9efe11600771861ae0d026fe0dbe642b073c91036ae
eecfaa08a7d85983eb13828c3903c532c0829802ff8b45e64e39079f65a5b84f
f91b65688eb31e6d5fc58cadc44319885bda8d78db2aab9fc4a268e3397d12d5
1ca0ffc79929344f97a6201c01a183d2c0c2702049048205649b91a784c7095b
8630b00c1ee0af742945873049981540863fe38a4e57cfc8647c85c069296284
599f169506c9df019471e0ca8fbc9abf7d1af1dcec4802e72bfb1d16138585e4
51918e0c421966a52ac29c21aa3822870959543691460c52ee43517b8588c365
888921e4560d3e28f72358325197f09baea07fccf9d10b238659be645e0bcdd5
e76534b21b52941a1e48267faae6abd43149987eb5385b44a422c0d6eb37c818
542c3553452c97e016c26d38a4c0b53ae8b156167a5e11b861b44bc488bb2bb0
cc652e3a1d12e616a502d1fcf31bfdcead55e2fdffc121ce85f525ba491feb54
7a3d16d85f65ad30e430dca5c603685abe8484d4c4144f91c5595a3fda9351e1
7f00eeccfcdb2e0465566192b23a9a78c14d62fdb3b1963c780f6855dd733820
89094e921ce09784e1f5408c620f6481d300d9fa6f8c23876a49281b0d425090
497b767614696424dcecad04f0767bb7601b99dd3bc5cc14d2dd77c09101fbd3
b6e725e5c68ba66a5a371fd6f3ca6351ef075645a3c03492f7fbfa225a5f3e01
b962177026d94e845953d5781064633edc41fcfed874e011304723a52fe8ebe5
d6efc5e69b9edf735067ba2d3ef221ee6244034df2469afb6056dba877ca9850
d4e20ce756a79a38e74b356019de03ca6651e54d1523e12ba9d9dd8e44dae7a9
20eba8784607fd0eaeb0b456bad6e739e264aa0a3f4d5cc5584e072cfc8e0a2b
949b4102d14fe3bbcd7ded2405718b0a7cd41deff91bd415340d6de94797c53c
d734d14a11be9fd9de57cc35175f24913e96f95315ad3c66ee102176e59a3b66
9c0b992d1b6c3cc131b33119eca4fae72f7553cb977dcffbd5ea29728ac5a645
eaab33042a0ad86e8b28fbdf79325e28c3801cd0f9d8a2b563aaebcebfc6540a
3ea351caa601ba8e5c5bfed770d61d7366f96d6bcde2db981b51e38ba35237ea
d55fa9c1cc2b3381131c1dbb39ddd7229d06e4b9d203d066666c8ad6aaa1a6df
0d346f843205c41a95f72df3027c9e6486a0088f8f8e7c9ef820e2e80766fc70
6c4df71ba5801863b29a917a16abcd824d9a94c9081208685f8a4398004d8afa
25087ba3fc81dceed46b7d6fc92d3b9557514899c5c97114ed722616b477ccfe
4f4e1faba32e6a24a091a7a1067628ecc8c421f8a967c6e0136a9c23ef642100
eb91c300975d6dc2c09da077e24fed0aeaf2876b91d0db63c4e347afd558f613
44eafd38df995bd98fcb720ce19023c26e0b1157e299e18d13fc7715bc1141d4
49f05fc6bf234ab5af157696a354495e45a818f41a007e601b49500e7554695a
4c21c8f6fb67d7b81379f6d3abff7b059f277e48c0291852c6af3e9d412526e6
b23653e0283af4ff8f06503ef135f552270f04d735cc21fbaa059025e7e32cc7
f03bdc406a167be87ce1442f285aba9aab9f4ff91daed0f04eadcc8e98a6ef67
0263a76e5b77baf65f979e202658c06d0deaa83aeb577e4872a916a87b8aad9e
9c9b22630d3b3b95b790f11f83bc6a52497a7c03264d70f55b6ee2ecf4f5af13
d45df4bcefc85437ad3d9b78e565e3dadc353e972fc21ba6f8ce701cb9c1aae6
5b2ffd89d65075bd6a5ae8f195d13165969e08c20a6143efa43a31963e81805b
584f93e1957713065d371abeef4ade6c3c024f37bcb2cc00895252332325359e
6f7425665f46bf49ed14cbdd14a659876670d962d36aab38e75c47db93978cc7
c30e5e33185c437cfc260caa8c3af8a0fe39d955fe41a89344db01f0f33632b5
71832eff64ed70de8b5dcf90e73e908b274441d7e34e14381c6a88bf71db2703
8b3037bcd5eb5a4a1c9b6067d2874b898c95dee5b114c10528dd3cd04d412719
0405f89ad7461b66eac5bb976c6eb433a43db8847ab105a9d6e004c1d08e17ec
c402862aeba56fa63297c5dab64a0f3dba016a5af5c761de36c9bdf0b375c0bd
6fd3c0fa3787e362103c3f96d6d1bca0fe0b3fa33c034f472204cef2949742fa
5b973d21b8af8e7c1ede70cb40860f7a58ac12a7709be24ba724166770215440
b0dd64dbe6af369ec9fc0d82e3c7a597884e4330109ab7631b8f8a62f0ce7dc1
7c9919d55bd997497b66e4089b640ada46e454b4cd90a45a5805eda36ec5db69
ca53cd3380d2f59c9cc4c6d52139cc33324161adabcf2eb44cfce47ba893bd4a
53d4480118c1ba64436d3771ded3182b2de8306237012aea5d5a2995abcbc097
e7535e259053c58c8de2a6c7c8d21ad6feec5907c2f6783541c68d00be43776a
8e766d72a8fa8123d819d38f1f53f36bd48adcc6f7a1455cc87453f96e550903
df9b819196a27061facc772b773dbd1444c37d3136a0d3158d79e98a70e8e030
dbaa42c202db2c0f8b03687f3d48b0f1783124024a5ebc0433990b1591459766
cbeaadebafa313226d839697f97e14cad664856368583b3e2e79609cac4c81af
e602dd4200cfa43fda4f1e48d68b13f27533ab9f3fd05a0143378b81d7e5bc77
eb8829d3d4e896af1c31ae42d39bc60f687306a10107727c8fc2fb98ad61af9b
7808b6afccd125519cc4f98828e53ac23388ffa188e885c64a97439cabfeeaca
48453cf4c6ac118ff667c21300d1c1ed5fef10e03f22e69e36248e476519a677
fd224e37ac95fa3d9aeea5b2482da91aec2f5e7a2b57a84ec7ec8699fc658175
7cfc8ed6bab56242725f615304b3cc39c20e8dd67136f864ad32605b0ea9ab0d
3662bb1ec7e317684a5a6afd8c3e83358db1392bdfb53dcb2d1624ba8772f701
a3626967c0a543a4b01d70aadea4d1c2c86383c6eb9a722a6c833c0c5f7e92ef
d67ff6bb9fc72a9933a446ac965c26c72ab279c5755890d21a9dd9f3862582bd
b1d9ccd1963a21bacd4be17d03819ab523f4473b20a87f120dcef914c72144e3
50ac33a94859de19fc1c45816ba504646b8b53410dedf6f2b1dd9b2f0b274901
3aeba319bc7d2e1adc99cbcff5d5ca41baf982ab06c3741fdde91b5ae8601be0
a690a8848d30eb1727351734daa8ec8fc416bb425309b1232d290ad42ab8d970
62812696531e1a5f6f87844f9ad9fe0cc660a7c4bb1f7c2d37ac95214fe2cb45
37f763691698dfc6cb42aee39ca3e37910a5caa4bbc93b20d7565936223f79d7
77d14971397338d791989bdd842a25eb4747a45fb3d0d853000205301a799d0f
1a597a34fad9c47ba0c27a82251b4d460f1de01fd0066bef08e4e6139412f5f7
b46ca9c6fc7b5e1bff8f5a24498699cc168b419278a41f5eb1845b41a298cda7
e237d3b149ebc1ebb02c33433c0cc8043bee875475cc389dfdb141fa31a67c9b
97f2bd9afcdcbd16b0682b3da7c3fe91ce83fa0eee07e155dbbafa26ff706798
c07bc149d963c31bd8b3d9736a21d45d5d7761f6d93111a10b978b32a00b6593
4ad2e4df3c2979ce6179aaa50a28348d3fd1743d482c16a2538eaaa17f6894fe
a19a21411ac73ff779f355ae9fca182a55d43f1080a60721ec087738c87987c4
699e24c19172afdf0461ef5d75820f2957bf75b1b396bf2a5462c7be537e67d2
8ddeb130863434670c75b36878888a430846e1f6565c9f0f529ad4e5d2386dc6
1f9fb0f4782a802c853cf5830763f5b9df5d77c5c3fef77c14fa64b966573237
b911aa353738e3ce2683d5a4612ddce6c8f50cd2c0b11912b7b09cb60590ea9b
25dad41363a82751aff5a9da8e1fb9643a84f3701b518b059e935a3199685c4b
f2afa07980ad93fcc6e7733a7c1cdb6d9ea9756eb985041297452d74381a609b
b8c3f9cc4c7b9ad09e57753602e856b5511cda7b0c9a5e0fbab6c9ef7d7e8d67
51760312ba04d771974ce5b6c18d9de0d4bf76d5e5b6cd7c3706f94693215165
881bf682231eb90cb99794177468d89877475bd1510e117d5f845f26fa303762
c92c2ced4c73a82afeedb275f48fb2cbbee350511004a58efd38e7002e91260e
40f0792b73dbc2158d542146aac2b860479bf6046c7e0e4edc26090205846fc8
e333cc60a4aa3990290508b400fb02f09560be4f200d272c713ba3b615e2b40b
9552cd70a67a098edf6f1bc4ea86732f1fcc762f513a1a004d39c1dd6d8d0650
24ad72b147c850945b7bfb29e830d4ef2e84d694422f1c89bc34ee502aca300d
f3c5a3e0ff8359668b11ea33ce14ef62cca8e2dfb8e5ab68d96a9a2552bf53af
81e78c84d96f3b1eda14e19ac07e75e3d3e5454200592a259bc950ccb398dc20
862141083a5190c1b2cb0aa0d8d3e8a5a3b21004fd002040c4b3ea35de14ccc1
ccd679d99308409a138c1ec129a71a1bb1443d1754f4763765b6409e8280e25b
5965f444cbb2a6b78bf8541250b992e39d0a4c14ed92c7b9ca642ec4002946f5
93ae24cc194f41357a86b418c8451b342860441b9d2e33c7f8a81ecfc0e5630d
23ee1fe752b2536ca59253c97aa18712f73f2b0335eeb0c2a26cbd98eedc669e
938831427718070324999284196cdbae8f16946b2bbf2b9f2a8e0a5928447383
1de3315a2dc0ae872b1036a8040d9c2a0c77a6c0c473c293ab7e19837fd227b3
52e8bf1bc817c76412f1d6abd47d809e989b3b2f89285d2693824df3191a6d1b
c8c9853f2bf81b8c96607a02b31d23d7495a590cf3f96d7328c4fd74452dc16c
2818512abf981c423d146e9d7a46bf2ef32a98dda4f6695f42532fabb8abba65
de15bf69090b724a247fcdfefd6f1a83cc35a049d3324bd39816f4ee13a5a38d
a73a3c3fb031daf9bf78fde0f8f6bdd0e897a3b24e090b54a955b232b2258e5f
2bfbfbe13db81f6abd243d73e3ff7d5d21527541ce6258732e85baddc7e56dc1
ae4b2bdead6d8de14b406a7234ab0c0fb1b6f129a7877adb864cfe9abef498ea
89232ee6639c0cea4dbd515a7a09aafbe65d04ec923e1200fcce3a2f684c07f2
02273eb6a93f7ae0771e7115385296132be25b258f67273c5a0f28f98627abf7
7751b7860e123e4a4e70422114eafe03c2606f854588ef418312650f11393ea1
5bfa6337b955355a183573948398e4438b3e13fc83a36f2d86cca04e6787f6a0
b29bfbb9aba924f37f5174e3ee892d16102d37b14d7743d9725ac7367217425c
f6263f30097ef995d81458db1357305c6044d6e490d9631e9ee456db83af1d45
4176174c786a03a7771b02c10daa800cfa6819f878c871f0b3230e5aeb87d8e9
b5d0e701fc2dd78a2ef5f9e3f0e060eeafc7ebeb813d13d4d77f1130256ceda9
4dd73b6e7b423d7f4c0c55f3491bbf6153b106b1316b9eb2ce72b263f05fda15
0b748d74b05f238982702f9564fb43259e9fd1f77d753f7a9bee8d81b2ea2d5b
abfa686d76582857a1a2338a5f8c2733728fdd4adffcc90331d2670c260111b7
6369299e8f79a9570d277107c81fbd22faf23d821471f8359f13980f282516b7
800ba8ecbac26e646e401a4d7a644fc3851749c5d19a915fb046bc40de6256a2
4184d666de6f54e6855060071896eea3338fbea7771f129a449e5bbb498f5edf
7dfb723d4838d670b76ae2842b726e757d534c24ebc471588ea38760f07b59c9
af9649132871a23ce328acfee7f583f7ff0486e07187a3d4942aaa9e6a38c615
43299873ae9c902dc5777ef58d396b5feb718509da30302ca268a9fe75e8343e
a5f4da3a39445369280cfca5442939a61f82f24b15bfc71d2e1b2880df011732
32527227875329ab6069618cde196f153e7ec3b1dc5fa627ed4f49a43550d02c
dd80cfc131d86dfd6ef64530f16be3c08b2fe804ba2c8b8ef512bac05420f780
9507cdc6aedbfa690c85a1bee6f424799dd0407f40e90051ce3d6b1020719e05
9187a78047533060ed3426bb7c314b179b608fdb19f181e4cf616e0eb850c408
85f2e1d9c5afa60dd6480166d7b227b731c8491237112df20561ef85e4a3d207
4bf8ba61da1e50699e9f9aba612c8a9a536cfaf7c9137b08aeee41148f96118a
43a901722f64a6457937eb18f9733fc353987b8e1fb9da5ec6c7229dad8d0456
54bcf4426f7148ef1942cd42954a8e5e5767ddd899f178f6f2443b93be25d5d6
1b9c06e68d653ba56f1506a88f9439a896b3f604880099548ab0dbc39b26237d
d1bbf9c1858716d858b94377708b44d800b95f77ba4f63577d1758719e208c1d
4757e53eec9ad4e1919e197b4507d1d43355c142e91c3d4d80064fa7fd5a85d7
c08f43cdb63e507726b4378853d6ad68ecc29592eef5a8b72869a2164552ae62
2f3f02dfa6cc2b5452898943fb90521daee4b1679df0d385b9ff15c9ac6c120b
30626415ed3415d06608b8b182f3efd579a539771a2af421119c43a5444f187b
55fb3b8668eafbcb63b919a2e2152aaa0d62613c37ca5002c6daea891411cb46
d58d815d7f231678185a0ea2b59ceb1030a8a9959f3426a666352ce86ddb3422
0f43b9f0695747f65b5c7d0c0bdaf97f76a67c396f24f5c3d277a375744310a9
f09dbe9f4501739523f301d94e6519029352ff5c1cced0d6dd89af38c49d8fdf
adbfc0baf374d259404ce7bfd2bf94a09a02e3463ab9c6d975190944acde8589
4ca4537a35ae86e26af1bd5e5bb7c7d24e671bd182153a5022047bd8c138016a
a85f3b7b62bfdbc06ae4dbe5e37528d6c6432b3db333a1347a09838c17b5de1b
2f9570c33e7580978d48effc18fa8e0fec834076990e0d4b8abaa2c336408011
53c5ffc858524015d49008574cf40c060b751c67395e8d39952b5514463241e8
aca46f92701b889780db90362ca74b5d13c5f9d3362a0b53d2dbaac2c54836e4
e42422aa713a20a5124ee36b353631a3933a5bbe368b0c4fd93aac08fdbdd557
59778a0b7ff59a185e2f9162c0ab4ce98bd37fdc7a85dddcddc3d5eba6020166
8eda23e041e6920b10912d251171fd3fa5bdbeae378e996d039c7b07bc4aca72
e81625f6f816a2bb469d2458518988aaddceb796926d796673c030554e7046b0
0cd49f488394682075dcd5dd193fbfd068636c9daf09f6eda12a326c0bef9abc
11578c932adf74009a4fb22ff201377253262e144366c9f9c140db1fc3074434
87b103b07a68a869b23a613b0c69f687632f9a89bd1e3c9bb4bcb6b0b4bebb49
8518f577692d8292730c3e761eb113bfd398b6f4f6e9aadee2f1baabd2cfef83
de4e0924b35836bd53198fee5eeeed8aa2c15c5117f242ca04ddaf1ffc9ae2fb
41a343b215b005e7267fd653e365a6842bad6be7d97a1df27404ab67126d88bc
79139d47b3a0ad8f8eb78d4a28a503754513393ce036f6671c1ccc0eab2befee
6f9d3b5afb869303af5580ea0b3568f8187087aca49310d17dc2e4b626f11ac2
bca641f79e15101aa92b013dbdea8c4f28357d0fc8bd2cba2678f0058adc282a
aa1cfcb544f6bef2b2b65488173e6fddb915382a02fd74806fe62fcaad8ca435
7bd0073647d2809fc510d91b38dd7a964668f72d76d45d3dace0d6383135880d
1082faf3595d0efb5b3026c0de0b4fe19d4713a8c1b31cbf82b9f4b458c75d74
3e7731d662b5b78afc79c962a6d73e92bd63dfeccdbfcee8c33cf0f1058dd6ee
ff9146cf33f535b4fe245110aea3ce3359accd39926187dc760dec775c0db374
a77f9712be3312264042527b98267aa3cad2c49d0e33aba1d87712bc4ff630f7
205019eaa70eee3cc1bd3e4c9f91aecdc8d8e1913ac869250c696a060b673c40
b2d0fc55673c8c262dfdb0a730228c96e5f95a8d01e4559af8ca5bb847d07581
5bed1aa246387bd73144b416fbe6652933956354c17a975209af6e2aceed8f07
8e2ab2dd70221bf9b174cbda7cfae19c1313f4d6e0530e40df9c2f752ef81118
e9cb012af24fe686924a3f5d145cb01942b72be7548f0d3a3ae8455ec4e422e4
459e5e231be8510628c22295e5ab6226afeffa45b24ecdfeeefb7ef8717869b7
758296e3249d4610ce84939d8f5a2b3dab176ec4b4e8902b1591099782f306ff
396a10ba8caaf297123c8c46b8d17cb7f4390c61d4f5ae73e04fe0ea12b2d9ca
2030cf4ba8d41484a101c9345f9849694ffdcdc3977382c54c4289c58960048a
45ac803c9a91a2846d4675917b01393c4d8c130c2110a0e3bcf46d79f3ed369d
19d5cd3be63489816cab5cb1c1eb46cf2550a4fb5ee579152bbd064e38616f6a
de92f96bc7517596f71b35ee3f176bb07861881c6cb050bef617d19b071fba4c
909a8a065aa936406c75e4936e9e138348f7321abf5ca3f4df3be8d0486dac3d
51c41b750a1e41f4004dab3de9ac98b33baab15feedb88c291d71c302adca759
2e1add8db5a26bde1fadb524588fb8b2971b86c8f31dc72eb3f2e1f3c673bccc
65c64b2c129b862bcfdad7f3672b4c6b99fc413728a83aa750b15708540a38a0
598ac513ddbbacae4b22fe4d2ea91b3eccf11bd5209032b3c744275c5dc194d8
952c4f91dc97ab263685a2c2af2ca0b0043307445ffaba4fc039abd736499882
51021b0ebf29492634dbc38a677e5bfbdd6716ac11d96de5459de1bdcabd7fc3
528baf83527ffc7e9257800590cf22d7fbf66e48597e33a39f056c80e8713d73
94a3eb7b3c65db7e7ca620db7ea44c67cab637c1c5d3606802ee0288ffc575e8
29e05b312a50f0fee6180d8ac0cf7d0ac87d5c6933f88ab16884e412fb545c48
c45e60e7e3322e9d1640abecf328ca705ef7f2eff6560f2b39b19354afb51515
07fe5c904481b7f5201b7bda802357b01755da1d3bfd21d941df316198e652af
5be4efc5e8d8e14d5ec9e3665881c74f660518b45aced85bf5b313c62e8ccd4a
9d2d7f32a741dc00fd5f34ac215ac596cbe8b143fa8cc948e52387797268555d
9a6d454ce1aa5cf8eba620a10483d8099c33520d88fbcaf0e1fb570b037b2bf0
44acf21d9daee9dbf1b0b311fbbc3505f78ebd7ddbc027a5eca10507216e1963
2b813b258e61fee6aef63c1570616eaa9f9dae95c212e758ab1e51da1fffdeb2
79260de737a48f3e1fe5d20475ce1223d006a31b1ddf3182ffa611db5ecd812a
4dd8a26a
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
cleartomark
{restore}if

%%EndResource
/F5_0 /CairoFont-0-0 1 1
[ /.notdef/d/o/x/y/g/e/n
  /s/a/r/c/h/t/period/m
  /l/space/w/i/b/H/T/M
  /L/p/u/q/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef]
pdfMakeFont
%%EndSetup
pdfStartPage
[] 0 d
1 i
0 j
0 J
10 M
1 w
/DeviceGray {} cs
[0] sc
/DeviceGray {} CS
[0] SC
false op
false OP
{} settransfer
q
q
36 35 105 471 re
W
/DeviceRGB {} cs
[1 1 1] sc
/DeviceRGB {} CS
[1 1 1] SC
1 w
0 J
1 j
[] 0 d
10 M
36 35 105 471 re
f
36 35 105 471 re
S
/DeviceRGB {} CS
[0 0 0] SC
119.301 484 m
119.301 474.059 105.285 466 88 466 c
70.715 466 56.699 474.059 56.699 484 c
56.699 493.941 70.715 502 88 502 c
105.285 502 119.301 493.941 119.301 484 c
S
/DeviceRGB {} cs
[0 0 0] sc
[1 0 0 1 0 0] Tm
0 0 Td
[9.999756 0 0 9.999756 69.5 481.5] Tm
0 0 Td
/F5_0 1 Tf
(\001) 0.556 Tj
31 TJm
(\002) 0.556 Tj
31 TJm
(\003) 0.5 Tj
-25 TJm
(\004) 0.5 Tj
-25 TJm
(\005) 0.556 Tj
31 TJm
(\006) 0.556 Tj
31 TJm
(\007) 0.556 Tj
/DeviceRGB {} CS
[0 0 0] SC
123.25 418 m
46.75 418 l
46.75 382 l
129.25 382 l
129.25 412 l
123.25 418 l
h
S
123.25 418 m
123.25 412 l
S
129.25 412 m
123.25 412 l
S
/DeviceRGB {} cs
[0 0 0] sc
[1 0 0 1 0 0] Tm
0 0 Td
[9.999756 0 0 9.999756 54.5 397.5] Tm
0 0 Td
/F5_0 1 Tf
(\010) 0.5 Tj
-25 TJm
(\006) 0.556 Tj
31 TJm
(\011) 0.556 Tj
31 TJm
(\012) 0.333 Tj
33 TJm
(\013) 0.5 Tj
-25 TJm
(\014) 0.556 Tj
31 TJm
(\001) 0.556 Tj
31 TJm
(\011) 0.556 Tj
31 TJm
(\015) 0.278 Tj
-22 TJm
(\011) 0.556 Tj
31 TJm
(\016) 0.278 Tj
-23 TJm
(\003) 0.5 Tj
-25 TJm
(\017) 0.832 Tj
8 TJm
(\020) 0.222 Tj
/DeviceRGB {} CS
[0 0 0] SC
88 465.609 m
88 454.773 88 440.602 88 428.293 c
S
/DeviceRGB {} cs
[0 0 0] sc
/DeviceRGB {} CS
[0 0 0] SC
91.5 428.082 m
88 418.082 l
84.5 428.082 l
91.5 428.082 l
h
f
91.5 428.082 m
88 418.082 l
84.5 428.082 l
91.5 428.082 l
h
S
/DeviceRGB {} cs
[0 0 0] sc
[1 0 0 1 0 0] Tm
0 0 Td
[9.999756 0 0 9.999756 88 439.5] Tm
0 0 Td
/F5_0 1 Tf
(\021) 0.278 Tj
-22 TJm
(\022) 0.721 Tj
-28 TJm
(\012) 0.333 Tj
33 TJm
(\023) 0.222 Tj
-3 TJm
(\015) 0.278 Tj
-22 TJm
(\006) 0.556 Tj
31 TJm
(\010) 0.5 Tj
/DeviceRGB {} CS
[0 0 0] SC
128.426 316 m
128.426 306.059 110.328 298 88 298 c
65.672 298 47.574 306.059 47.574 316 c
47.574 325.941 65.672 334 88 334 c
110.328 334 128.426 325.941 128.426 316 c
S
/DeviceRGB {} cs
[0 0 0] sc
[1 0 0 1 0 0] Tm
0 0 Td
[9.999756 0 0 9.999756 61.5 313.5] Tm
0 0 Td
/F5_0 1 Tf
(\001) 0.556 Tj
31 TJm
(\002) 0.556 Tj
31 TJm
(\003) 0.5 Tj
-25 TJm
(\004) 0.5 Tj
-25 TJm
(\023) 0.222 Tj
-3 TJm
(\007) 0.556 Tj
31 TJm
(\001) 0.556 Tj
31 TJm
(\006) 0.556 Tj
31 TJm
(\003) 0.5 Tj
-25 TJm
(\006) 0.556 Tj
30 TJm
(\012) 0.333 Tj
/DeviceRGB {} CS
[0 0 0] SC
122 250 m
48 250 l
48 214 l
128 214 l
128 244 l
122 250 l
h
S
122 250 m
122 244 l
S
128 244 m
122 244 l
S
/DeviceRGB {} cs
[0 0 0] sc
[1 0 0 1 0 0] Tm
0 0 Td
[9.999756 0 0 9.999756 56 229.5] Tm
0 0 Td
/F5_0 1 Tf
(\001) 0.556 Tj
31 TJm
(\002) 0.556 Tj
31 TJm
(\003) 0.5 Tj
-25 TJm
(\004) 0.5 Tj
-25 TJm
(\010) 0.5 Tj
-25 TJm
(\006) 0.556 Tj
31 TJm
(\011) 0.556 Tj
31 TJm
(\012) 0.333 Tj
33 TJm
(\013) 0.5 Tj
-25 TJm
(\014) 0.556 Tj
31 TJm
(\016) 0.278 Tj
-23 TJm
(\001) 0.556 Tj
31 TJm
(\024) 0.556 Tj
/DeviceRGB {} CS
[0 0 0] SC
88 297.609 m
88 286.773 88 272.602 88 260.293 c
S
/DeviceRGB {} cs
[0 0 0] sc
/DeviceRGB {} CS
[0 0 0] SC
91.5 260.082 m
88 250.082 l
84.5 260.082 l
91.5 260.082 l
h
f
91.5 260.082 m
88 250.082 l
84.5 260.082 l
91.5 260.082 l
h
S
/DeviceRGB {} cs
[0 0 0] sc
[1 0 0 1 0 0] Tm
0 0 Td
[9.999756 0 0 9.999756 88 271.5] Tm
0 0 Td
/F5_0 1 Tf
(\021) 0.278 Tj
-22 TJm
(\022) 0.721 Tj
-28 TJm
(\012) 0.333 Tj
33 TJm
(\023) 0.222 Tj
-3 TJm
(\015) 0.278 Tj
-22 TJm
(\006) 0.556 Tj
31 TJm
(\010) 0.5 Tj
/DeviceRGB {} CS
[0 0 0] SC
136.289 148 m
136.289 138.059 114.672 130 88 130 c
61.328 130 39.711 138.059 39.711 148 c
39.711 157.941 61.328 166 88 166 c
114.672 166 136.289 157.941 136.289 148 c
S
/DeviceRGB {} cs
[0 0 0] sc
[1 0 0 1 0 0] Tm
0 0 Td
[9.999756 0 0 9.999756 54.5 145.5] Tm
0 0 Td
/F5_0 1 Tf
(\001) 0.556 Tj
31 TJm
(\002) 0.556 Tj
31 TJm
(\003) 0.5 Tj
-25 TJm
(\004) 0.5 Tj
-25 TJm
(\010) 0.5 Tj
-25 TJm
(\006) 0.556 Tj
31 TJm
(\011) 0.556 Tj
31 TJm
(\012) 0.333 Tj
33 TJm
(\013) 0.5 Tj
-25 TJm
(\014) 0.556 Tj
31 TJm
(\016) 0.278 Tj
-23 TJm
(\013) 0.5 Tj
-25 TJm
(\005) 0.556 Tj
31 TJm
(\023) 0.222 Tj
/DeviceRGB {} CS
[0 0 0] SC
136.125 61 m
136.125 49.164 114.578 39.57 88 39.57 c
61.422 39.57 39.875 49.164 39.875 61 c
39.875 72.836 61.422 82.43 88 82.43 c
114.578 82.43 136.125 72.836 136.125 61 c
S
/DeviceRGB {} cs
[0 0 0] sc
[1 0 0 1 0 0] Tm
0 0 Td
[9.999756 0 0 9.999756 62 64] Tm
0 0 Td
/F5_0 1 Tf
(\025) 0.721 Tj
-28 TJm
(\026) 0.61 Tj
11 TJm
(\027) 0.832 Tj
8 TJm
(\030) 0.556 Tj
31 TJm
(\021) 0.278 Tj
-22 TJm
(\031) 0.556 Tj
31 TJm
(\011) 0.556 Tj
31 TJm
(\005) 0.556 Tj
31 TJm
(\006) 0.556 Tj
0.300007 -1.100027 Td
(\023) 0.222 Tj
-3 TJm
(\007) 0.556 Tj
31 TJm
(\021) 0.278 Tj
-22 TJm
(\024) 0.556 Tj
31 TJm
(\012) 0.333 Tj
33 TJm
(\002) 0.556 Tj
31 TJm
(\022) 0.721 Tj
-28 TJm
(\010) 0.5 Tj
-25 TJm
(\006) 0.556 Tj
31 TJm
(\012) 0.333 Tj
/DeviceRGB {} CS
[0 0 0] SC
65.395 131.844 m
55.582 123.238 47.281 111.84 52 100 c
53.711 95.703 56.164 91.617 58.996 87.82 c
S
/DeviceRGB {} cs
[0 0 0] sc
/DeviceRGB {} CS
[0 0 0] SC
61.828 89.895 m
65.66 80.02 l
56.504 85.348 l
61.828 89.895 l
h
f
61.828 89.895 m
65.66 80.02 l
56.504 85.348 l
61.828 89.895 l
h
S
/DeviceRGB {} cs
[0 0 0] sc
[1 0 0 1 0 0] Tm
0 0 Td
[9.999756 0 0 9.999756 52 103.5] Tm
0 0 Td
/F5_0 1 Tf
(\021) 0.278 Tj
-22 TJm
(\005) 0.556 Tj
31 TJm
(\006) 0.556 Tj
31 TJm
(\015) 0.278 Tj
-22 TJm
(\021) 0.278 Tj
-22 TJm
(\012) 0.333 Tj
33 TJm
(\006) 0.556 Tj
31 TJm
(\010) 0.5 Tj
-25 TJm
(\032) 0.556 Tj
31 TJm
(\020) 0.222 Tj
-3 TJm
(\015) 0.278 Tj
-22 TJm
(\010) 0.5 Tj
-25 TJm
(\021) 0.278 Tj
/DeviceRGB {} CS
[0 0 0] SC
99.348 81.715 m
103.281 90.82 106.211 101.848 104 112 c
103.375 114.875 102.488 117.801 101.453 120.668 c
S
/DeviceRGB {} cs
[0 0 0] sc
/DeviceRGB {} CS
[0 0 0] SC
98.152 119.488 m
97.508 130.062 l
104.605 122.199 l
98.152 119.488 l
h
f
98.152 119.488 m
97.508 130.062 l
104.605 122.199 l
98.152 119.488 l
h
S
/DeviceRGB {} cs
[0 0 0] sc
[1 0 0 1 0 0] Tm
0 0 Td
[9.999756 0 0 9.999756 104 103.5] Tm
0 0 Td
/F5_0 1 Tf
(\021) 0.278 Tj
-22 TJm
(\033) 0.556 Tj
31 TJm
(\032) 0.556 Tj
31 TJm
(\006) 0.556 Tj
31 TJm
(\012) 0.333 Tj
33 TJm
(\004) 0.5 Tj
-25 TJm
(\021) 0.278 Tj
/DeviceRGB {} CS
[0 0 0] SC
88 381.609 m
88 370.773 88 356.602 88 344.293 c
S
/DeviceRGB {} cs
[0 0 0] sc
/DeviceRGB {} CS
[0 0 0] SC
91.5 344.082 m
88 334.082 l
84.5 344.082 l
91.5 344.082 l
h
f
91.5 344.082 m
88 334.082 l
84.5 344.082 l
91.5 344.082 l
h
S
/DeviceRGB {} cs
[0 0 0] sc
[1 0 0 1 0 0] Tm
0 0 Td
[9.999756 0 0 9.999756 88 355.5] Tm
0 0 Td
/F5_0 1 Tf
(\021) 0.278 Tj
-22 TJm
(\012) 0.333 Tj
33 TJm
(\006) 0.556 Tj
31 TJm
(\011) 0.556 Tj
31 TJm
(\001) 0.556 Tj
31 TJm
(\010) 0.5 Tj
/DeviceRGB {} CS
[0 0 0] SC
88 213.609 m
88 202.773 88 188.602 88 176.293 c
S
/DeviceRGB {} cs
[0 0 0] sc
/DeviceRGB {} CS
[0 0 0] SC
91.5 176.082 m
88 166.082 l
84.5 176.082 l
91.5 176.082 l
h
f
91.5 176.082 m
88 166.082 l
84.5 176.082 l
91.5 176.082 l
h
S
/DeviceRGB {} cs
[0 0 0] sc
[1 0 0 1 0 0] Tm
0 0 Td
[9.999756 0 0 9.999756 88 187.5] Tm
0 0 Td
/F5_0 1 Tf
(\021) 0.278 Tj
-22 TJm
(\012) 0.333 Tj
33 TJm
(\006) 0.556 Tj
31 TJm
(\011) 0.556 Tj
31 TJm
(\001) 0.556 Tj
31 TJm
(\010) 0.5 Tj
Q
Q
showpage
%%PageTrailer
pdfEndPage
%%Trailer
end
%%DocumentSuppliedResources:
%%+ font CairoFont-0-0
%%EOF
468'>4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503
/****************************************************************************
**
** Copyright (C) 2011 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$
** 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.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

/*!
    \class QGraphicsScene
    \brief The QGraphicsScene class provides a surface for managing a large
    number of 2D graphical items.
    \since 4.2
    \ingroup graphicsview-api


    The class serves as a container for QGraphicsItems. It is used together
    with QGraphicsView for visualizing graphical items, such as lines,
    rectangles, text, or even custom items, on a 2D surface. QGraphicsScene is
    part of the \l{Graphics View Framework}.

    QGraphicsScene also provides functionality that lets you efficiently
    determine both the location of items, and for determining what items are
    visible within an arbitrary area on the scene. With the QGraphicsView
    widget, you can either visualize the whole scene, or zoom in and view only
    parts of the scene.

    Example:

    \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsscene.cpp 0

    Note that QGraphicsScene has no visual appearance of its own; it only
    manages the items. You need to create a QGraphicsView widget to visualize
    the scene.

    To add items to a scene, you start off by constructing a QGraphicsScene
    object. Then, you have two options: either add your existing QGraphicsItem
    objects by calling addItem(), or you can call one of the convenience
    functions addEllipse(), addLine(), addPath(), addPixmap(), addPolygon(),
    addRect(), or addText(), which all return a pointer to the newly added item.
    The dimensions of the items added with these functions are relative to the
    item's coordinate system, and the items position is initialized to (0,
    0) in the scene.

    You can then visualize the scene using QGraphicsView. When the scene
    changes, (e.g., when an item moves or is transformed) QGraphicsScene
    emits the changed() signal. To remove an item, call removeItem().

    QGraphicsScene uses an indexing algorithm to manage the location of items
    efficiently. By default, a BSP (Binary Space Partitioning) tree is used; an
    algorithm suitable for large scenes where most items remain static (i.e.,
    do not move around). You can choose to disable this index by calling
    setItemIndexMethod(). For more information about the available indexing
    algorithms, see the itemIndexMethod property.

    The scene's bounding rect is set by calling setSceneRect(). Items can be
    placed at any position on the scene, and the size of the scene is by
    default unlimited. The scene rect is used only for internal bookkeeping,
    maintaining the scene's item index. If the scene rect is unset,
    QGraphicsScene will use the bounding area of all items, as returned by
    itemsBoundingRect(), as the scene rect. However, itemsBoundingRect() is a
    relatively time consuming function, as it operates by collecting
    positional information for every item on the scene. Because of this, you
    should always set the scene rect when operating on large scenes.

    One of QGraphicsScene's greatest strengths is its ability to efficiently
    determine the location of items. Even with millions of items on the scene,
    the items() functions can determine the location of an item within few
    milliseconds. There are several overloads to items(): one that finds items
    at a certain position, one that finds items inside or intersecting with a
    polygon or a rectangle, and more. The list of returned items is sorted by
    stacking order, with the topmost item being the first item in the list.
    For convenience, there is also an itemAt() function that returns the
    topmost item at a given position.

    QGraphicsScene maintains selection information for the scene. To select
    items, call setSelectionArea(), and to clear the current selection, call
    clearSelection(). Call selectedItems() to get the list of all selected
    items.

    \section1 Event Handling and Propagation

    Another responsibility that QGraphicsScene has, is to propagate events
    from QGraphicsView. To send an event to a scene, you construct an event
    that inherits QEvent, and then send it using, for example,
    QApplication::sendEvent(). event() is responsible for dispatching
    the event to the individual items. Some common events are handled by
    convenience event handlers. For example, key press events are handled by
    keyPressEvent(), and mouse press events are handled by mousePressEvent().

    Key events are delivered to the \e {focus item}. To set the focus item,
    you can either call setFocusItem(), passing an item that accepts focus, or
    the item itself can call QGraphicsItem::setFocus().  Call focusItem() to
    get the current focus item. For compatibility with widgets, the scene also
    maintains its own focus information. By default, the scene does not have
    focus, and all key events are discarded. If setFocus() is called, or if an
    item on the scene gains focus, the scene automatically gains focus. If the
    scene has focus, hasFocus() will return true, and key events will be
    forwarded to the focus item, if any. If the scene loses focus, (i.e.,
    someone calls clearFocus()) while an item has focus, the scene will
    maintain its item focus information, and once the scene regains focus, it
    will make sure the last focus item regains focus.

    For mouse-over effects, QGraphicsScene dispatches \e {hover
    events}. If an item accepts hover events (see
    QGraphicsItem::acceptHoverEvents()), it will receive a \l
    {QEvent::}{GraphicsSceneHoverEnter} event when the mouse enters
    its area. As the mouse continues moving inside the item's area,
    QGraphicsScene will send it \l {QEvent::}{GraphicsSceneHoverMove}
    events. When the mouse leaves the item's area, the item will
    receive a \l {QEvent::}{GraphicsSceneHoverLeave} event.

    All mouse events are delivered to the current \e {mouse grabber}
    item. An item becomes the scene's mouse grabber if it accepts
    mouse events (see QGraphicsItem::acceptedMouseButtons()) and it
    receives a mouse press. It stays the mouse grabber until it
    receives a mouse release when no other mouse buttons are
    pressed. You can call mouseGrabberItem() to determine what item is
    currently grabbing the mouse.

    \sa QGraphicsItem, QGraphicsView
*/

/*!
    \enum QGraphicsScene::SceneLayer
    \since 4.3

    This enum describes the rendering layers in a QGraphicsScene. When
    QGraphicsScene draws the scene contents, it renders each of these layers
    separately, in order.

    Each layer represents a flag that can be OR'ed together when calling
    functions such as invalidate() or QGraphicsView::invalidateScene().

    \value ItemLayer The item layer. QGraphicsScene renders all items are in
    this layer by calling the virtual function drawItems(). The item layer is
    drawn after the background layer, but before the foreground layer.

    \value BackgroundLayer The background layer. QGraphicsScene renders the
    scene's background in this layer by calling the virtual function
    drawBackground(). The background layer is drawn first of all layers.

    \value ForegroundLayer The foreground layer. QGraphicsScene renders the
    scene's foreground in this layer by calling the virtual function
    drawForeground().  The foreground layer is drawn last of all layers.

    \value AllLayers All layers; this value represents a combination of all
    three layers.

    \sa invalidate(), QGraphicsView::invalidateScene()
*/

/*!
    \enum QGraphicsScene::ItemIndexMethod

    This enum describes the indexing algorithms QGraphicsScene provides for
    managing positional information about items on the scene.

    \value BspTreeIndex A Binary Space Partitioning tree is applied. All
    QGraphicsScene's item location algorithms are of an order close to
    logarithmic complexity, by making use of binary search. Adding, moving and
    removing items is logarithmic. This approach is best for static scenes
    (i.e., scenes where most items do not move).

    \value NoIndex No index is applied. Item location is of linear complexity,
    as all items on the scene are searched. Adding, moving and removing items,
    however, is done in constant time. This approach is ideal for dynamic
    scenes, where many items are added, moved or removed continuously.

    \sa setItemIndexMethod(), bspTreeDepth
*/

#include "qgraphicsscene.h"

#ifndef QT_NO_GRAPHICSVIEW

#include "qgraphicsitem.h"
#include "qgraphicsitem_p.h"
#include "qgraphicslayout.h"
#include "qgraphicsscene_p.h"
#include "qgraphicssceneevent.h"
#include "qgraphicsview.h"
#include "qgraphicsview_p.h"
#include "qgraphicswidget.h"
#include "qgraphicswidget_p.h"
#include "qgraphicssceneindex_p.h"
#include "qgraphicsscenebsptreeindex_p.h"
#include "qgraphicsscenelinearindex_p.h"

#include <QtCore/qdebug.h>
#include <QtCore/qlist.h>
#include <QtCore/qmath.h>
#include <QtCore/qrect.h>
#include <QtCore/qset.h>
#include <QtCore/qstack.h>
#include <QtCore/qtimer.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/QMetaMethod>
#include <QtGui/qapplication.h>
#include <QtGui/qdesktopwidget.h>
#include <QtGui/qevent.h>
#include <QtGui/qgraphicslayout.h>
#include <QtGui/qgraphicsproxywidget.h>
#include <QtGui/qgraphicswidget.h>
#include <QtGui/qmatrix.h>
#include <QtGui/qpaintengine.h>
#include <QtGui/qpainter.h>
#include <QtGui/qpixmapcache.h>
#include <QtGui/qpolygon.h>
#include <QtGui/qstyleoption.h>
#include <QtGui/qtooltip.h>
#include <QtGui/qtransform.h>
#include <QtGui/qinputcontext.h>
#include <QtGui/qgraphicseffect.h>
#ifndef QT_NO_ACCESSIBILITY
# include <QtGui/qaccessible.h>
#endif

#include <private/qapplication_p.h>
#include <private/qobject_p.h>
#ifdef Q_WS_X11
#include <private/qt_x11_p.h>
#endif
#include <private/qgraphicseffect_p.h>
#include <private/qgesturemanager_p.h>
#include <private/qpathclipper_p.h>

// #define GESTURE_DEBUG
#ifndef GESTURE_DEBUG
# define DEBUG if (0) qDebug
#else
# define DEBUG qDebug
#endif

QT_BEGIN_NAMESPACE

bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event);

static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraphicsSceneMouseEvent *mouseEvent)
{
    hover->setWidget(mouseEvent->widget());
    hover->setPos(mouseEvent->pos());
    hover->setScenePos(mouseEvent->scenePos());
    hover->setScreenPos(mouseEvent->screenPos());
    hover->setLastPos(mouseEvent->lastPos());
    hover->setLastScenePos(mouseEvent->lastScenePos());
    hover->setLastScreenPos(mouseEvent->lastScreenPos());
    hover->setModifiers(mouseEvent->modifiers());
    hover->setAccepted(mouseEvent->isAccepted());
}

/*!
    \internal
*/
QGraphicsScenePrivate::QGraphicsScenePrivate()
    : indexMethod(QGraphicsScene::BspTreeIndex),
      index(0),
      lastItemCount(0),
      hasSceneRect(false),
      dirtyGrowingItemsBoundingRect(true),
      updateAll(false),
      calledEmitUpdated(false),
      processDirtyItemsEmitted(false),
      needSortTopLevelItems(true),
      holesInTopLevelSiblingIndex(false),
      topLevelSequentialOrdering(true),
      scenePosDescendantsUpdatePending(false),
      stickyFocus(false),
      hasFocus(false),
      lastMouseGrabberItemHasImplicitMouseGrab(false),
      allItemsIgnoreHoverEvents(true),
      allItemsUseDefaultCursor(true),
      painterStateProtection(true),
      sortCacheEnabled(false),
      allItemsIgnoreTouchEvents(true),
      selectionChanging(0),
      rectAdjust(2),
      focusItem(0),
      lastFocusItem(0),
      passiveFocusItem(0),
      tabFocusFirst(0),
      activePanel(0),
      lastActivePanel(0),
      activationRefCount(0),
      childExplicitActivation(0),
      lastMouseGrabberItem(0),
      dragDropItem(0),
      enterWidget(0),
      lastDropAction(Qt::IgnoreAction),
      style(0)
{
}

/*!
    \internal
*/
void QGraphicsScenePrivate::init()
{
    Q_Q(QGraphicsScene);

    index = new QGraphicsSceneBspTreeIndex(q);

    // Keep this index so we can check for connected slots later on.
    changedSignalIndex = signalIndex("changed(QList<QRectF>)");
    processDirtyItemsIndex = q->metaObject()->indexOfSlot("_q_processDirtyItems()");
    polishItemsIndex = q->metaObject()->indexOfSlot("_q_polishItems()");

    qApp->d_func()->scene_list.append(q);
    q->update();
}

/*!
    \internal
*/
QGraphicsScenePrivate *QGraphicsScenePrivate::get(QGraphicsScene *q)
{
    return q->d_func();
}

void QGraphicsScenePrivate::_q_emitUpdated()
{
    Q_Q(QGraphicsScene);
    calledEmitUpdated = false;

    if (dirtyGrowingItemsBoundingRect) {
        if (!hasSceneRect) {
            const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect;
            growingItemsBoundingRect |= q->itemsBoundingRect();
            if (oldGrowingItemsBoundingRect != growingItemsBoundingRect)
                emit q->sceneRectChanged(growingItemsBoundingRect);
        }
        dirtyGrowingItemsBoundingRect = false;
    }

    // Ensure all views are connected if anything is connected. This disables
    // the optimization that items send updates directly to the views, but it
    // needs to happen in order to keep compatibility with the behavior from
    // Qt 4.4 and backward.
    if (isSignalConnected(changedSignalIndex)) {
        for (int i = 0; i < views.size(); ++i) {
            QGraphicsView *view = views.at(i);
            if (!view->d_func()->connectedToScene) {
                view->d_func()->connectedToScene = true;
                q->connect(q, SIGNAL(changed(QList<QRectF>)),
                           views.at(i), SLOT(updateScene(QList<QRectF>)));
            }
        }
    } else {
        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.
        for (int i = 0; i < views.size(); ++i)
            views.at(i)->d_func()->dispatchPendingUpdateRequests();
        return;
    }

    // Notify the changes to anybody interested.
    QList<QRectF> oldUpdatedRects;
    oldUpdatedRects = updateAll ? (QList<QRectF>() << q->sceneRect()) : updatedRects;
    updateAll = false;
    updatedRects.clear();
    emit q->changed(oldUpdatedRects);
}

/*!
    \internal

    ### This function is almost identical to QGraphicsItemPrivate::addChild().
*/
void QGraphicsScenePrivate::registerTopLevelItem(QGraphicsItem *item)
{
    item->d_ptr->ensureSequentialSiblingIndex();
    needSortTopLevelItems = true; // ### maybe false
    item->d_ptr->siblingIndex = topLevelItems.size();
    topLevelItems.append(item);
}

/*!
    \internal

    ### This function is almost identical to QGraphicsItemPrivate::removeChild().
*/
void QGraphicsScenePrivate::unregisterTopLevelItem(QGraphicsItem *item)
{
    if (!holesInTopLevelSiblingIndex)
        holesInTopLevelSiblingIndex = item->d_ptr->siblingIndex != topLevelItems.size() - 1;
    if (topLevelSequentialOrdering && !holesInTopLevelSiblingIndex)
        topLevelItems.removeAt(item->d_ptr->siblingIndex);
    else
        topLevelItems.removeOne(item);
    // NB! Do not use topLevelItems.removeAt(item->d_ptr->siblingIndex) because
    // the item is not guaranteed to be at the index after the list is sorted
    // (see ensureSortedTopLevelItems()).
    item->d_ptr->siblingIndex = -1;
    if (topLevelSequentialOrdering)
        topLevelSequentialOrdering = !holesInTopLevelSiblingIndex;
}

/*!
    \internal
*/
void QGraphicsScenePrivate::_q_polishItems()
{
    if (unpolishedItems.isEmpty())
        return;

    const QVariant booleanTrueVariant(true);
    QGraphicsItem *item = 0;
    QGraphicsItemPrivate *itemd = 0;
    const int oldUnpolishedCount = unpolishedItems.count();

    for (int i = 0; i < oldUnpolishedCount; ++i) {
        item = unpolishedItems.at(i);
        if (!item)
            continue;
        itemd = item->d_ptr.data();
        itemd->pendingPolish = false;
        if (!itemd->explicitlyHidden) {
            item->itemChange(QGraphicsItem::ItemVisibleChange, booleanTrueVariant);
            item->itemChange(QGraphicsItem::ItemVisibleHasChanged, booleanTrueVariant);
        }
        if (itemd->isWidget) {
            QEvent event(QEvent::Polish);
            QApplication::sendEvent((QGraphicsWidget *)item, &event);
        }
    }

    if (unpolishedItems.count() == oldUnpolishedCount) {
        // No new items were added to the vector.
        unpolishedItems.clear();
    } else {
        // New items were appended; keep them and remove the old ones.
        unpolishedItems.remove(0, oldUnpolishedCount);
        unpolishedItems.squeeze();
        QMetaObject::invokeMethod(q_ptr, "_q_polishItems", Qt::QueuedConnection);
    }
}

void QGraphicsScenePrivate::_q_processDirtyItems()
{
    processDirtyItemsEmitted = false;

    if (updateAll) {
        Q_ASSERT(calledEmitUpdated);
        // No need for further processing (except resetting the dirty states).
        // The growingItemsBoundingRect is updated in _q_emitUpdated.
        for (int i = 0; i < topLevelItems.size(); ++i)
            resetDirtyItem(topLevelItems.at(i), /*recursive=*/true);
        return;
    }

    const bool wasPendingSceneUpdate = calledEmitUpdated;
    const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect;

    // Process items recursively.
    for (int i = 0; i < topLevelItems.size(); ++i)
        processDirtyItemsRecursive(topLevelItems.at(i));

    dirtyGrowingItemsBoundingRect = false;
    if (!hasSceneRect && oldGrowingItemsBoundingRect != growingItemsBoundingRect)
        emit q_func()->sceneRectChanged(growingItemsBoundingRect);

    if (wasPendingSceneUpdate)
        return;

    for (int i = 0; i < views.size(); ++i)
        views.at(i)->d_func()->processPendingUpdates();

    if (calledEmitUpdated) {
        // We did a compatibility QGraphicsScene::update in processDirtyItemsRecursive
        // and we cannot wait for the control to reach the eventloop before the
        // changed signal is emitted, so we emit it now.
        _q_emitUpdated();
    }

    // Immediately dispatch all pending update requests on the views.
    for (int i = 0; i < views.size(); ++i)
        views.at(i)->d_func()->dispatchPendingUpdateRequests();
}

/*!
    \internal
*/
void QGraphicsScenePrivate::setScenePosItemEnabled(QGraphicsItem *item, bool enabled)
{
    QGraphicsItem *p = item->d_ptr->parent;
    while (p) {
        p->d_ptr->scenePosDescendants = enabled;
        p = p->d_ptr->parent;
    }
    if (!enabled && !scenePosDescendantsUpdatePending) {
        scenePosDescendantsUpdatePending = true;
        QMetaObject::invokeMethod(q_func(), "_q_updateScenePosDescendants", Qt::QueuedConnection);
    }
}

/*!
    \internal
*/
void QGraphicsScenePrivate::registerScenePosItem(QGraphicsItem *item)
{
    scenePosItems.insert(item);
    setScenePosItemEnabled(item, true);
}

/*!
    \internal
*/
void QGraphicsScenePrivate::unregisterScenePosItem(QGraphicsItem *item)
{
    scenePosItems.remove(item);
    setScenePosItemEnabled(item, false);
}

/*!
    \internal
*/
void QGraphicsScenePrivate::_q_updateScenePosDescendants()
{
    foreach (QGraphicsItem *item, scenePosItems) {
        QGraphicsItem *p = item->d_ptr->parent;
        while (p) {
            p->d_ptr->scenePosDescendants = 1;
            p = p->d_ptr->parent;
        }
    }
    scenePosDescendantsUpdatePending = false;
}

/*!
    \internal

    Schedules an item for removal. This function leaves some stale indexes
    around in the BSP tree if called from the item's destructor; these will
    be cleaned up the next time someone triggers purgeRemovedItems().

    Note: This function might get called from QGraphicsItem's destructor. \a item is
    being destroyed, so we cannot call any pure virtual functions on it (such
    as boundingRect()). Also, it is unnecessary to update the item's own state
    in any way.
*/
void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item)
{
    Q_Q(QGraphicsScene);

    // Clear focus on the item to remove any reference in the focusWidget chain.
    item->clearFocus();

    markDirty(item, QRectF(), /*invalidateChildren=*/false, /*force=*/false,
              /*ignoreOpacity=*/false, /*removingItemFromScene=*/true);

    if (item->d_ptr->inDestructor) {
        // The item is actually in its destructor, we call the special method in the index.
        index->deleteItem(item);
    } else {
        // Can potentially call item->boundingRect() (virtual function), that's why
        // we only can call this function if the item is not in its destructor.
        index->removeItem(item);
    }

    item->d_ptr->clearSubFocus();

    if (item->flags() & QGraphicsItem::ItemSendsScenePositionChanges)
        unregisterScenePosItem(item);

    QGraphicsScene *oldScene = item->d_func()->scene;
    item->d_func()->scene = 0;

    //We need to remove all children first because they might use their parent
    //attributes (e.g. sceneTransform).
    if (!item->d_ptr->inDestructor) {
        // Remove all children recursively
        for (int i = 0; i < item->d_ptr->children.size(); ++i)
            q->removeItem(item->d_ptr->children.at(i));
    }

    if (!item->d_ptr->inDestructor && item == tabFocusFirst) {
        QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
        widget->d_func()->fixFocusChainBeforeReparenting(0, oldScene, 0);
    }

    // Unregister focus proxy.
    item->d_ptr->resetFocusProxy();

    // Remove from parent, or unregister from toplevels.
    if (QGraphicsItem *parentItem = item->parentItem()) {
        if (parentItem->scene()) {
            Q_ASSERT_X(parentItem->scene() == q, "QGraphicsScene::removeItem",
                       "Parent item's scene is different from this item's scene");
            item->setParentItem(0);
        }
    } else {
        unregisterTopLevelItem(item);
    }

    // Reset the mouse grabber and focus item data.
    if (item == focusItem)
        focusItem = 0;
    if (item == lastFocusItem)
        lastFocusItem = 0;
    if (item == passiveFocusItem)
        passiveFocusItem = 0;
    if (item == activePanel) {
        // ### deactivate...
        activePanel = 0;
    }
    if (item == lastActivePanel)
        lastActivePanel = 0;

    // Cancel active touches
    {
        QMap<int, QGraphicsItem *>::iterator it = itemForTouchPointId.begin();
        while (it != itemForTouchPointId.end()) {
            if (it.value() == item) {
                sceneCurrentTouchPoints.remove(it.key());
                it = itemForTouchPointId.erase(it);
            } else {
                ++it;
            }
        }
    }

    // Disable selectionChanged() for individual items
    ++selectionChanging;
    int oldSelectedItemsSize = selectedItems.size();

    // Update selected & hovered item bookkeeping
    selectedItems.remove(item);
    hoverItems.removeAll(item);
    cachedItemsUnderMouse.removeAll(item);
    if (item->d_ptr->pendingPolish) {
        const int unpolishedIndex = unpolishedItems.indexOf(item);
        if (unpolishedIndex != -1)
            unpolishedItems[unpolishedIndex] = 0;
        item->d_ptr->pendingPolish = false;
    }
    resetDirtyItem(item);

    //We remove all references of item from the sceneEventFilter arrays
    QMultiMap<QGraphicsItem*, QGraphicsItem*>::iterator iterator = sceneEventFilters.begin();
    while (iterator != sceneEventFilters.end()) {
        if (iterator.value() == item || iterator.key() == item)
            iterator = sceneEventFilters.erase(iterator);
        else
            ++iterator;
    }

    if (item->isPanel() && item->isVisible() && item->panelModality() != QGraphicsItem::NonModal)
        leaveModal(item);

    // Reset the mouse grabber and focus item data.
    if (mouseGrabberItems.contains(item))
        ungrabMouse(item, /* item is dying */ item->d_ptr->inDestructor);

    // Reset the keyboard grabber
    if (keyboardGrabberItems.contains(item))
        ungrabKeyboard(item, /* item is dying */ item->d_ptr->inDestructor);

    // Reset the last mouse grabber item
    if (item == lastMouseGrabberItem)
        lastMouseGrabberItem = 0;

    // Reset the current drop item
    if (item == dragDropItem)
        dragDropItem = 0;

    // Reenable selectionChanged() for individual items
    --selectionChanging;
    if (!selectionChanging && selectedItems.size() != oldSelectedItemsSize)
        emit q->selectionChanged();

#ifndef QT_NO_GESTURES
    QHash<QGesture *, QGraphicsObject *>::iterator it;
    for (it = gestureTargets.begin(); it != gestureTargets.end();) {
        if (it.value() == item)
            it = gestureTargets.erase(it);
        else
            ++it;
    }

    QGraphicsObject *dummy = static_cast<QGraphicsObject *>(item);
    cachedTargetItems.removeOne(dummy);
    cachedItemGestures.remove(dummy);
    cachedAlreadyDeliveredGestures.remove(dummy);

    foreach (Qt::GestureType gesture, item->d_ptr->gestureContext.keys())
        ungrabGesture(item, gesture);
#endif // QT_NO_GESTURES
}

/*!
    \internal
*/
void QGraphicsScenePrivate::setActivePanelHelper(QGraphicsItem *item, bool duringActivationEvent)
{
    Q_Q(QGraphicsScene);
    if (item && item->scene() != q) {
        qWarning("QGraphicsScene::setActivePanel: item %p must be part of this scene",
                 item);
        return;
    }

    // Ensure the scene has focus when we change panel activation.
    q->setFocus(Qt::ActiveWindowFocusReason);

    // Find the item's panel.
    QGraphicsItem *panel = item ? item->panel() : 0;
    lastActivePanel = panel ? activePanel : 0;
    if (panel == activePanel || (!q->isActive() && !duringActivationEvent))
        return;

    // Deactivate the last active panel.
    if (activePanel) {
        if (QGraphicsItem *fi = activePanel->focusItem()) {
            // Remove focus from the current focus item.
            if (fi == q->focusItem())
                q->setFocusItem(0, Qt::ActiveWindowFocusReason);
        }

        QEvent event(QEvent::WindowDeactivate);
        q->sendEvent(activePanel, &event);
    } else if (panel && !duringActivationEvent) {
        // Deactivate the scene if changing activation to a panel.
        QEvent event(QEvent::WindowDeactivate);
        foreach (QGraphicsItem *item, q->items()) {
            if (item->isVisible() && !item->isPanel() && !item->parentItem())
                q->sendEvent(item, &event);
        }
    }

    // Update activate state.
    activePanel = panel;
    QEvent event(QEvent::ActivationChange);
    QApplication::sendEvent(q, &event);

    // Activate
    if (panel) {
        QEvent event(QEvent::WindowActivate);
        q->sendEvent(panel, &event);

        // Set focus on the panel's focus item.
        if (QGraphicsItem *focusItem = panel->focusItem())
            focusItem->setFocus(Qt::ActiveWindowFocusReason);
    } else if (q->isActive()) {
        // Activate the scene
        QEvent event(QEvent::WindowActivate);
        foreach (QGraphicsItem *item, q->items()) {
            if (item->isVisible() && !item->isPanel() && !item->parentItem())
                q->sendEvent(item, &event);
        }
    }
}

/*!
    \internal
*/
void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item,
                                               Qt::FocusReason focusReason)
{
    Q_Q(QGraphicsScene);
    if (item == focusItem)
        return;

    // Clear focus if asked to set focus on something that can't
    // accept input focus.
    if (item && (!(item->flags() & QGraphicsItem::ItemIsFocusable)
                 || !item->isVisible() || !item->isEnabled())) {
        item = 0;
    }

    // Set focus on the scene if an item requests focus.
    if (item) {
        q->setFocus(focusReason);
        if (item == focusItem)
            return;
    }

    if (focusItem) {
        lastFocusItem = focusItem;

#ifndef QT_NO_IM
        if (lastFocusItem
            && (lastFocusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) {
            // Close any external input method panel. This happens
            // automatically by removing WA_InputMethodEnabled on
            // the views, but if we are changing focus, we have to
            // do it ourselves.
            for (int i = 0; i < views.size(); ++i)
                if (views.at(i)->inputContext())
                    views.at(i)->inputContext()->reset();
        }

        focusItem = 0;
        QFocusEvent event(QEvent::FocusOut, focusReason);
        sendEvent(lastFocusItem, &event);
#endif //QT_NO_IM
    }

    // This handles the case that the item has been removed from the
    // scene in response to the FocusOut event.
    if (item && item->scene() != q)
        item = 0;

    if (item)
        focusItem = item;
    updateInputMethodSensitivityInViews();

#ifndef QT_NO_ACCESSIBILITY
    if (focusItem) {
        if (QGraphicsObject *focusObj = focusItem->toGraphicsObject()) {
            QAccessible::updateAccessibility(focusObj, 0, QAccessible::Focus);
        }
    }
#endif
    if (item) {
        QFocusEvent event(QEvent::FocusIn, focusReason);
        sendEvent(item, &event);
    }
}

/*!
    \internal
*/
void QGraphicsScenePrivate::addPopup(QGraphicsWidget *widget)
{
    Q_ASSERT(widget);
    Q_ASSERT(!popupWidgets.contains(widget));
    popupWidgets << widget;
    if (QGraphicsWidget *focusWidget = widget->focusWidget()) {
        focusWidget->setFocus(Qt::PopupFocusReason);
    } else {
        grabKeyboard((QGraphicsItem *)widget);
        if (focusItem && popupWidgets.size() == 1) {
            QFocusEvent event(QEvent::FocusOut, Qt::PopupFocusReason);
            sendEvent(focusItem, &event);
        }
    }
    grabMouse((QGraphicsItem *)widget);
}

/*!
    \internal

    Remove \a widget from the popup list. Important notes:

    \a widget is guaranteed to be in the list of popups, but it might not be
    the last entry; you can hide any item in the pop list before the others,
    and this must cause all later mouse grabbers to lose the grab.
*/
void QGraphicsScenePrivate::removePopup(QGraphicsWidget *widget, bool itemIsDying)
{
    Q_ASSERT(widget);
    int index = popupWidgets.indexOf(widget);
    Q_ASSERT(index != -1);

    for (int i = popupWidgets.size() - 1; i >= index; --i) {
        QGraphicsWidget *widget = popupWidgets.takeLast();
        ungrabMouse(widget, itemIsDying);
        if (focusItem && popupWidgets.isEmpty()) {
            QFocusEvent event(QEvent::FocusIn, Qt::PopupFocusReason);
            sendEvent(focusItem, &event);
        } else if (keyboardGrabberItems.contains(static_cast<QGraphicsItem *>(widget))) {
            ungrabKeyboard(static_cast<QGraphicsItem *>(widget), itemIsDying);
        }
        if (!itemIsDying && widget->isVisible()) {
            widget->QGraphicsItem::d_ptr->setVisibleHelper(false, /* explicit = */ false);
        }
    }
}

/*!
    \internal
*/
void QGraphicsScenePrivate::grabMouse(QGraphicsItem *item, bool implicit)
{
    // Append to list of mouse grabber items, and send a mouse grab event.
    if (mouseGrabberItems.contains(item)) {
        if (mouseGrabberItems.last() == item) {
            Q_ASSERT(!implicit);
            if (!lastMouseGrabberItemHasImplicitMouseGrab) {
                qWarning("QGraphicsItem::grabMouse: already a mouse grabber");
            } else {
                // Upgrade to an explicit mouse grab
                lastMouseGrabberItemHasImplicitMouseGrab = false;
            }
        } else {
            qWarning("QGraphicsItem::grabMouse: already blocked by mouse grabber: %p",
                     mouseGrabberItems.last());
        }
        return;
    }

    // Send ungrab event to the last grabber.
    if (!mouseGrabberItems.isEmpty()) {
        QGraphicsItem *last = mouseGrabberItems.last();
        if (lastMouseGrabberItemHasImplicitMouseGrab) {
            // Implicit mouse grab is immediately lost.
            last->ungrabMouse();
        } else {
            // Just send ungrab event to current grabber.
            QEvent ungrabEvent(QEvent::UngrabMouse);
            sendEvent(last, &ungrabEvent);
        }
    }

    mouseGrabberItems << item;
    lastMouseGrabberItemHasImplicitMouseGrab = implicit;

    // Send grab event to current grabber.
    QEvent grabEvent(QEvent::GrabMouse);
    sendEvent(item, &grabEvent);
}

/*!
    \internal
*/
void QGraphicsScenePrivate::ungrabMouse(QGraphicsItem *item, bool itemIsDying)
{
    int index = mouseGrabberItems.indexOf(item);
    if (index == -1) {
        qWarning("QGraphicsItem::ungrabMouse: not a mouse grabber");
        return;
    }

    if (item != mouseGrabberItems.last()) {
        // Recursively ungrab the next mouse grabber until we reach this item
        // to ensure state consistency.
        ungrabMouse(mouseGrabberItems.at(index + 1), itemIsDying);
    }
    if (!popupWidgets.isEmpty() && item == popupWidgets.last()) {
        // If the item is a popup, go via removePopup to ensure state
        // consistency and that it gets hidden correctly - beware that
        // removePopup() reenters this function to continue removing the grab.
        removePopup((QGraphicsWidget *)item, itemIsDying);
        return;
    }

    // Send notification about mouse ungrab.
    if (!itemIsDying) {
        QEvent event(QEvent::UngrabMouse);
        sendEvent(item, &event);
    }

    // Remove the item from the list of grabbers. Whenever this happens, we
    // reset the implicitGrab (there can be only ever be one implicit grabber
    // in a scene, and it is always the latest grabber; if the implicit grab
    // is lost, it is not automatically regained.
    mouseGrabberItems.takeLast();
    lastMouseGrabberItemHasImplicitMouseGrab = false;

    // Send notification about mouse regrab. ### It's unfortunate that all the
    // items get a GrabMouse event, but this is a rare case with a simple
    // implementation and it does ensure a consistent state.
    if (!itemIsDying && !mouseGrabberItems.isEmpty()) {
        QGraphicsItem *last = mouseGrabberItems.last();
        QEvent event(QEvent::GrabMouse);
        sendEvent(last, &event);
    }
}

/*!
    \internal
*/
void QGraphicsScenePrivate::clearMouseGrabber()
{
    if (!mouseGrabberItems.isEmpty())
        mouseGrabberItems.first()->ungrabMouse();
    lastMouseGrabberItem = 0;
}

/*!
    \internal
*/
void QGraphicsScenePrivate::grabKeyboard(QGraphicsItem *item)
{
    if (keyboardGrabberItems.contains(item)) {
        if (keyboardGrabberItems.last() == item)
            qWarning("QGraphicsItem::grabKeyboard: already a keyboard grabber");
        else
            qWarning("QGraphicsItem::grabKeyboard: already blocked by keyboard grabber: %p",
                     keyboardGrabberItems.last());
        return;
    }

    // Send ungrab event to the last grabber.
    if (!keyboardGrabberItems.isEmpty()) {
        // Just send ungrab event to current grabber.
        QEvent ungrabEvent(QEvent::UngrabKeyboard);
        sendEvent(keyboardGrabberItems.last(), &ungrabEvent);
    }

    keyboardGrabberItems << item;

    // Send grab event to current grabber.
    QEvent grabEvent(QEvent::GrabKeyboard);
    sendEvent(item, &grabEvent);
}

/*!
    \internal
*/
void QGraphicsScenePrivate::ungrabKeyboard(QGraphicsItem *item, bool itemIsDying)
{
    int index = keyboardGrabberItems.lastIndexOf(item);
    if (index == -1) {
        qWarning("QGraphicsItem::ungrabKeyboard: not a keyboard grabber");
        return;
    }
    if (item != keyboardGrabberItems.last()) {
        // Recursively ungrab the topmost keyboard grabber until we reach this
        // item to ensure state consistency.
        ungrabKeyboard(keyboardGrabberItems.at(index + 1), itemIsDying);
    }

    // Send notification about keyboard ungrab.
    if (!itemIsDying) {
        QEvent event(QEvent::UngrabKeyboard);
        sendEvent(item, &event);
    }

    // Remove the item from the list of grabbers.
    keyboardGrabberItems.takeLast();

    // Send notification about mouse regrab.
    if (!itemIsDying && !keyboardGrabberItems.isEmpty()) {
        QGraphicsItem *last = keyboardGrabberItems.last();
        QEvent event(QEvent::GrabKeyboard);
        sendEvent(last, &event);
    }
}

/*!
    \internal
*/
void QGraphicsScenePrivate::clearKeyboardGrabber()
{
    if (!keyboardGrabberItems.isEmpty())
        ungrabKeyboard(keyboardGrabberItems.first());
}

void QGraphicsScenePrivate::enableMouseTrackingOnViews()
{
    foreach (QGraphicsView *view, views)
        view->viewport()->setMouseTracking(true);
}

/*!
    Returns all items for the screen position in \a event.
*/
QList<QGraphicsItem *> QGraphicsScenePrivate::itemsAtPosition(const QPoint &/*screenPos*/,
                                                              const QPointF &scenePos,
                                                              QWidget *widget) const
{
    Q_Q(const QGraphicsScene);
    QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0;
    if (!view)
        return q->items(scenePos, Qt::IntersectsItemShape, Qt::DescendingOrder, QTransform());

    const QRectF pointRect(scenePos, QSizeF(1, 1));
    if (!view->isTransformed())
        return q->items(pointRect, Qt::IntersectsItemShape, Qt::DescendingOrder);

    const QTransform viewTransform = view->viewportTransform();
    return q->items(pointRect, Qt::IntersectsItemShape,
                    Qt::DescendingOrder, viewTransform);
}

/*!
    \internal
*/
void QGraphicsScenePrivate::storeMouseButtonsForMouseGrabber(QGraphicsSceneMouseEvent *event)
{
    for (int i = 0x1; i <= 0x10; i <<= 1) {
        if (event->buttons() & i) {
            mouseGrabberButtonDownPos.insert(Qt::MouseButton(i),
                                             mouseGrabberItems.last()->d_ptr->genericMapFromScene(event->scenePos(),
                                                                                                  event->widget()));
            mouseGrabberButtonDownScenePos.insert(Qt::MouseButton(i), event->scenePos());
            mouseGrabberButtonDownScreenPos.insert(Qt::MouseButton(i), event->screenPos());
        }
    }
}

/*!
    \internal
*/
void QGraphicsScenePrivate::installSceneEventFilter(QGraphicsItem *watched, QGraphicsItem *filter)
{
    sceneEventFilters.insert(watched, filter);
}

/*!
    \internal
*/
void QGraphicsScenePrivate::removeSceneEventFilter(QGraphicsItem *watched, QGraphicsItem *filter)
{
    if (!sceneEventFilters.contains(watched))
        return;

    QMultiMap<QGraphicsItem *, QGraphicsItem *>::Iterator it = sceneEventFilters.lowerBound(watched);
    QMultiMap<QGraphicsItem *, QGraphicsItem *>::Iterator end = sceneEventFilters.upperBound(watched);
    do {
        if (it.value() == filter)
            it = sceneEventFilters.erase(it);
        else
            ++it;
    } while (it != end);
}

/*!
  \internal
*/
bool QGraphicsScenePrivate::filterDescendantEvent(QGraphicsItem *item, QEvent *event)
{
    if (item && (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorFiltersChildEvents)) {
        QGraphicsItem *parent = item->parentItem();
        while (parent) {
            if (parent->d_ptr->filtersDescendantEvents && parent->sceneEventFilter(item, event))
                return true;
            if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorFiltersChildEvents))
                return false;
            parent = parent->parentItem();
        }
    }
    return false;
}

/*!
    \internal
*/
bool QGraphicsScenePrivate::filterEvent(QGraphicsItem *item, QEvent *event)
{
    if (item && !sceneEventFilters.contains(item))
        return false;

    QMultiMap<QGraphicsItem *, QGraphicsItem *>::Iterator it = sceneEventFilters.lowerBound(item);
    QMultiMap<QGraphicsItem *, QGraphicsItem *>::Iterator end = sceneEventFilters.upperBound(item);
    while (it != end) {
        // ### The filterer and filteree might both be deleted.
        if (it.value()->sceneEventFilter(it.key(), event))
            return true;
        ++it;
    }
    return false;
}

/*!
    \internal

    This is the final dispatch point for any events from the scene to the
    item. It filters the event first - if the filter returns true, the event
    is considered to have been eaten by the filter, and is therefore stopped
    (the default filter returns false). Then/otherwise, if the item is
    enabled, the event is sent; otherwise it is stopped.
*/
bool QGraphicsScenePrivate::sendEvent(QGraphicsItem *item, QEvent *event)
{
    if (QGraphicsObject *object = item->toGraphicsObject()) {
#ifndef QT_NO_GESTURES
        QGestureManager *gestureManager = QApplicationPrivate::instance()->gestureManager;
        if (gestureManager) {
            if (gestureManager->filterEvent(object, event))
                return true;
        }
#endif // QT_NO_GESTURES
    }

    if (filterEvent(item, event))
        return false;
    if (filterDescendantEvent(item, event))
        return false;
    if (!item || !item->isEnabled())
        return false;
    if (QGraphicsObject *o = item->toGraphicsObject()) {
        bool spont = event->spontaneous();
        if (spont ? qt_sendSpontaneousEvent(o, event) : QApplication::sendEvent(o, event))
            return true;
        event->spont = spont;
    }
    return item->sceneEvent(event);
}

/*!
    \internal
*/
void QGraphicsScenePrivate::cloneDragDropEvent(QGraphicsSceneDragDropEvent *dest,
                                               QGraphicsSceneDragDropEvent *source)
{
    dest->setWidget(source->widget());
    dest->setPos(source->pos());
    dest->setScenePos(source->scenePos());
    dest->setScreenPos(source->screenPos());
    dest->setButtons(source->buttons());
    dest->setModifiers(source->modifiers());
    dest->setPossibleActions(source->possibleActions());
    dest->setProposedAction(source->proposedAction());
    dest->setDropAction(source->dropAction());
    dest->setSource(source->source());
    dest->setMimeData(source->mimeData());
}

/*!
    \internal
*/
void QGraphicsScenePrivate::sendDragDropEvent(QGraphicsItem *item,
                                              QGraphicsSceneDragDropEvent *dragDropEvent)
{
    dragDropEvent->setPos(item->d_ptr->genericMapFromScene(dragDropEvent->scenePos(), dragDropEvent->widget()));
    sendEvent(item, dragDropEvent);
}

/*!
    \internal
*/
void QGraphicsScenePrivate::sendHoverEvent(QEvent::Type type, QGraphicsItem *item,
                                           QGraphicsSceneHoverEvent *hoverEvent)
{
    QGraphicsSceneHoverEvent event(type);
    event.setWidget(hoverEvent->widget());
    event.setPos(item->d_ptr->genericMapFromScene(hoverEvent->scenePos(), hoverEvent->widget()));
    event.setScenePos(hoverEvent->scenePos());
    event.setScreenPos(hoverEvent->screenPos());
    event.setLastPos(item->d_ptr->genericMapFromScene(hoverEvent->lastScenePos(), hoverEvent->widget()));
    event.setLastScenePos(hoverEvent->lastScenePos());
    event.setLastScreenPos(hoverEvent->lastScreenPos());
    event.setModifiers(hoverEvent->modifiers());
    sendEvent(item, &event);
}

/*!
    \internal
*/
void QGraphicsScenePrivate::sendMouseEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
    if (mouseEvent->button() == 0 && mouseEvent->buttons() == 0 && lastMouseGrabberItemHasImplicitMouseGrab) {
        // ### This is a temporary fix for until we get proper mouse
        // grab events.
        clearMouseGrabber();
        return;
    }

    QGraphicsItem *item = mouseGrabberItems.last();
    if (item->isBlockedByModalPanel())
        return;

    for (int i = 0x1; i <= 0x10; i <<= 1) {
        Qt::MouseButton button = Qt::MouseButton(i);
        mouseEvent->setButtonDownPos(button, mouseGrabberButtonDownPos.value(button, item->d_ptr->genericMapFromScene(mouseEvent->scenePos(), mouseEvent->widget())));
        mouseEvent->setButtonDownScenePos(button, mouseGrabberButtonDownScenePos.value(button, mouseEvent->scenePos()));
        mouseEvent->setButtonDownScreenPos(button, mouseGrabberButtonDownScreenPos.value(button, mouseEvent->screenPos()));
    }
    mouseEvent->setPos(item->d_ptr->genericMapFromScene(mouseEvent->scenePos(), mouseEvent->widget()));
    mouseEvent->setLastPos(item->d_ptr->genericMapFromScene(mouseEvent->lastScenePos(), mouseEvent->widget()));
    sendEvent(item, mouseEvent);
}

/*!
    \internal
*/
void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent)
{
    Q_Q(QGraphicsScene);

    // Ignore by default, unless we find a mouse grabber that accepts it.
    mouseEvent->ignore();

    // Deliver to any existing mouse grabber.
    if (!mouseGrabberItems.isEmpty()) {
        if (mouseGrabberItems.last()->isBlockedByModalPanel())
            return;
        // The event is ignored by default, but we disregard the event's
        // accepted state after delivery; the mouse is grabbed, after all.
        sendMouseEvent(mouseEvent);
        return;
    }

    // Start by determining the number of items at the current position.
    // Reuse value from earlier calculations if possible.
    if (cachedItemsUnderMouse.isEmpty()) {
        cachedItemsUnderMouse = itemsAtPosition(mouseEvent->screenPos(),
                                                mouseEvent->scenePos(),
                                                mouseEvent->widget());
    }

    // Update window activation.
    QGraphicsItem *topItem = cachedItemsUnderMouse.value(0);
    QGraphicsWidget *newActiveWindow = topItem ? topItem->window() : 0;
    if (newActiveWindow && newActiveWindow->isBlockedByModalPanel(&topItem)) {
        // pass activation to the blocking modal window
        newActiveWindow = topItem ? topItem->window() : 0;
    }

    if (newActiveWindow != q->activeWindow())
        q->setActiveWindow(newActiveWindow);

    // Set focus on the topmost enabled item that can take focus.
    bool setFocus = false;

    foreach (QGraphicsItem *item, cachedItemsUnderMouse) {
        if (item->isBlockedByModalPanel()
            || (item->d_ptr->flags & QGraphicsItem::ItemStopsFocusHandling)) {
            // Make sure we don't clear focus.
            setFocus = true;
            break;
        }
        if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable))) {
            if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
                setFocus = true;
                if (item != q->focusItem() && item->d_ptr->mouseSetsFocus)
                    q->setFocusItem(item, Qt::MouseFocusReason);
                break;
            }
        }
        if (item->isPanel())
            break;
        if (item->d_ptr->flags & QGraphicsItem::ItemStopsClickFocusPropagation)
            break;
    }

    // Check for scene modality.
    bool sceneModality = false;
    for (int i = 0; i < modalPanels.size(); ++i) {
        if (modalPanels.at(i)->panelModality() == QGraphicsItem::SceneModal) {
            sceneModality = true;
            break;
        }
    }

    // If nobody could take focus, clear it.
    if (!stickyFocus && !setFocus && !sceneModality)
        q->setFocusItem(0, Qt::MouseFocusReason);

    // Any item will do.
    if (sceneModality && cachedItemsUnderMouse.isEmpty())
        cachedItemsUnderMouse << modalPanels.first();

    // Find a mouse grabber by sending mouse press events to all mouse grabber
    // candidates one at a time, until the event is accepted. It's accepted by
    // default, so the receiver has to explicitly ignore it for it to pass
    // through.
    foreach (QGraphicsItem *item, cachedItemsUnderMouse) {
        if (!(item->acceptedMouseButtons() & mouseEvent->button())) {
            // Skip items that don't accept the event's mouse button.
            continue;
        }

        // Check if this item is blocked by a modal panel and deliver the mouse event to the
        // blocking panel instead of this item if blocked.
        (void) item->isBlockedByModalPanel(&item);

        grabMouse(item, /* implicit = */ true);
        mouseEvent->accept();

        // check if the item we are sending to are disabled (before we send the event)
        bool disabled = !item->isEnabled();
        bool isPanel = item->isPanel();
        if (mouseEvent->type() == QEvent::GraphicsSceneMouseDoubleClick
            && item != lastMouseGrabberItem && lastMouseGrabberItem) {
            // If this item is different from the item that received the last
            // mouse event, and mouseEvent is a doubleclick event, then the
            // event is converted to a press. Known limitation:
            // Triple-clicking will not generate a doubleclick, though.
            QGraphicsSceneMouseEvent mousePress(QEvent::GraphicsSceneMousePress);
            mousePress.spont = mouseEvent->spont;
            mousePress.accept();
            mousePress.setButton(mouseEvent->button());
            mousePress.setButtons(mouseEvent->buttons());
            mousePress.setScreenPos(mouseEvent->screenPos());
            mousePress.setScenePos(mouseEvent->scenePos());
            mousePress.setModifiers(mouseEvent->modifiers());
            mousePress.setWidget(mouseEvent->widget());
            mousePress.setButtonDownPos(mouseEvent->button(),
                                        mouseEvent->buttonDownPos(mouseEvent->button()));
            mousePress.setButtonDownScenePos(mouseEvent->button(),
                                             mouseEvent->buttonDownScenePos(mouseEvent->button()));
            mousePress.setButtonDownScreenPos(mouseEvent->button(),
                                              mouseEvent->buttonDownScreenPos(mouseEvent->button()));
            sendMouseEvent(&mousePress);
            mouseEvent->setAccepted(mousePress.isAccepted());
        } else {
            sendMouseEvent(mouseEvent);
        }

        bool dontSendUngrabEvents = mouseGrabberItems.isEmpty() || mouseGrabberItems.last() != item;
        if (disabled) {
            ungrabMouse(item, /* itemIsDying = */ dontSendUngrabEvents);
            break;
        }
        if (mouseEvent->isAccepted()) {
            if (!mouseGrabberItems.isEmpty())
                storeMouseButtonsForMouseGrabber(mouseEvent);
            lastMouseGrabberItem = item;
            return;
        }
        ungrabMouse(item, /* itemIsDying = */ dontSendUngrabEvents);

        // Don't propagate through panels.
        if (isPanel)
            break;
    }

    // Is the event still ignored? Then the mouse press goes to the scene.
    // Reset the mouse grabber, clear the selection, clear focus, and leave
    // the event ignored so that it can propagate through the originating
    // view.
    if (!mouseEvent->isAccepted()) {
        clearMouseGrabber();

        QGraphicsView *view = mouseEvent->widget() ? qobject_cast<QGraphicsView *>(mouseEvent->widget()->parentWidget()) : 0;
        bool dontClearSelection = view && view->dragMode() == QGraphicsView::ScrollHandDrag;
        if (!dontClearSelection) {
            // Clear the selection if the originating view isn't in scroll
            // hand drag mode. The view will clear the selection if no drag
            // happened.
            q->clearSelection();
        }
    }
}

/*!
    \internal

    Ensures that the list of toplevels is sorted by insertion order, and that
    the siblingIndexes are packed (no gaps), and start at 0.

    ### This function is almost identical to
    QGraphicsItemPrivate::ensureSequentialSiblingIndex().
*/
void QGraphicsScenePrivate::ensureSequentialTopLevelSiblingIndexes()
{
    if (!topLevelSequentialOrdering) {
        qSort(topLevelItems.begin(), topLevelItems.end(), QGraphicsItemPrivate::insertionOrder);
        topLevelSequentialOrdering = true;
        needSortTopLevelItems = 1;
    }
    if (holesInTopLevelSiblingIndex) {
        holesInTopLevelSiblingIndex = 0;
        for (int i = 0; i < topLevelItems.size(); ++i)
            topLevelItems[i]->d_ptr->siblingIndex = i;
    }
}

/*!
    \internal

    Set the font and propagate the changes if the font is different from the
    current font.
*/
void QGraphicsScenePrivate::setFont_helper(const QFont &font)
{
    if (this->font == font && this->font.resolve() == font.resolve())
        return;
    updateFont(font);
}

/*!
    \internal

    Resolve the scene's font against the application font, and propagate the
    changes too all items in the scene.
*/
void QGraphicsScenePrivate::resolveFont()
{
    QFont naturalFont = QApplication::font();
    naturalFont.resolve(0);
    QFont resolvedFont = font.resolve(naturalFont);
    updateFont(resolvedFont);
}

/*!
    \internal

    Update the font, and whether or not it has changed, reresolve all fonts in
    the scene.
*/
void QGraphicsScenePrivate::updateFont(const QFont &font)
{
    Q_Q(QGraphicsScene);

    // Update local font setting.
    this->font = font;

    // Resolve the fonts of all top-level widget items, or widget items
    // whose parent is not a widget.
    foreach (QGraphicsItem *item, q->items()) {
        if (!item->parentItem()) {
            // Resolvefont for an item is a noop operation, but
            // every item can be a widget, or can have a widget
            // childre.
            item->d_ptr->resolveFont(font.resolve());
        }
    }

    // Send the scene a FontChange event.
    QEvent event(QEvent::FontChange);
    QApplication::sendEvent(q, &event);
}

/*!
    \internal

    Set the palette and propagate the changes if the palette is different from
    the current palette.
*/
void QGraphicsScenePrivate::setPalette_helper(const QPalette &palette)
{
    if (this->palette == palette && this->palette.resolve() == palette.resolve())
        return;
    updatePalette(palette);
}

/*!
    \internal

    Resolve the scene's palette against the application palette, and propagate
    the changes too all items in the scene.
*/
void QGraphicsScenePrivate::resolvePalette()
{
    QPalette naturalPalette = QApplication::palette();
    naturalPalette.resolve(0);
    QPalette resolvedPalette = palette.resolve(naturalPalette);
    updatePalette(resolvedPalette);
}

/*!
    \internal

    Update the palette, and whether or not it has changed, reresolve all
    palettes in the scene.
*/
void QGraphicsScenePrivate::updatePalette(const QPalette &palette)
{
    Q_Q(QGraphicsScene);

    // Update local palette setting.
    this->palette = palette;

    // Resolve the palettes of all top-level widget items, or widget items
    // whose parent is not a widget.
    foreach (QGraphicsItem *item, q->items()) {
        if (!item->parentItem()) {
            // Resolvefont for an item is a noop operation, but
            // every item can be a widget, or can have a widget
            // childre.
            item->d_ptr->resolvePalette(palette.resolve());
        }
    }

    // Send the scene a PaletteChange event.
    QEvent event(QEvent::PaletteChange);
    QApplication::sendEvent(q, &event);
}

/*!
    Constructs a QGraphicsScene object. The \a parent parameter is
    passed to QObject's constructor.
*/
QGraphicsScene::QGraphicsScene(QObject *parent)
    : QObject(*new QGraphicsScenePrivate, parent)
{
    d_func()->init();
}

/*!
    Constructs a QGraphicsScene object, using \a sceneRect for its
    scene rectangle. The \a parent parameter is passed to QObject's
    constructor.

    \sa sceneRect
*/
QGraphicsScene::QGraphicsScene(const QRectF &sceneRect, QObject *parent)
    : QObject(*new QGraphicsScenePrivate, parent)
{
    d_func()->init();
    setSceneRect(sceneRect);
}

/*!
    Constructs a QGraphicsScene object, using the rectangle specified
    by (\a x, \a y), and the given \a width and \a height for its
    scene rectangle. The \a parent parameter is passed to QObject's
    constructor.

    \sa sceneRect
*/
QGraphicsScene::QGraphicsScene(qreal x, qreal y, qreal width, qreal height, QObject *parent)
    : QObject(*new QGraphicsScenePrivate, parent)
{
    d_func()->init();
    setSceneRect(x, y, width, height);
}

/*!
  Removes and deletes all items from the scene object
  before destroying the scene object. The scene object
  is removed from the application's global scene list,
  and it is removed from all associated views.
*/
QGraphicsScene::~QGraphicsScene()
{
    Q_D(QGraphicsScene);

    // Remove this scene from qApp's global scene list.
    qApp->d_func()->scene_list.removeAll(this);

    clear();

    // Remove this scene from all associated views.
    for (int j = 0; j < d->views.size(); ++j)
        d->views.at(j)->setScene(0);
}

/*!
    \property QGraphicsScene::sceneRect
    \brief the scene rectangle; the bounding rectangle of the scene

    The scene rectangle defines the extent of the scene. It is
    primarily used by QGraphicsView to determine the view's default
    scrollable area, and by QGraphicsScene to manage item indexing.

    If unset, or if set to a null QRectF, sceneRect() will return the largest
    bounding rect of all items on the scene since the scene was created (i.e.,
    a rectangle that grows when items are added to or moved in the scene, but
    never shrinks).

    \sa width(), height(), QGraphicsView::sceneRect
*/
QRectF QGraphicsScene::sceneRect() const
{
    Q_D(const QGraphicsScene);
    if (d->hasSceneRect)
        return d->sceneRect;

    if (d->dirtyGrowingItemsBoundingRect) {
        // Lazily update the growing items bounding rect
        QGraphicsScenePrivate *thatd = const_cast<QGraphicsScenePrivate *>(d);
        QRectF oldGrowingBoundingRect = thatd->growingItemsBoundingRect;
        thatd->growingItemsBoundingRect |= itemsBoundingRect();
        thatd->dirtyGrowingItemsBoundingRect = false;
        if (oldGrowingBoundingRect != thatd->growingItemsBoundingRect)
            emit const_cast<QGraphicsScene *>(this)->sceneRectChanged(thatd->growingItemsBoundingRect);
    }
    return d->growingItemsBoundingRect;
}
void QGraphicsScene::setSceneRect(const QRectF &rect)
{
    Q_D(QGraphicsScene);
    if (rect != d->sceneRect) {
        d->hasSceneRect = !rect.isNull();
        d->sceneRect = rect;
        emit sceneRectChanged(d->hasSceneRect ? rect : d->growingItemsBoundingRect);
    }
}

/*!
     \fn qreal QGraphicsScene::width() const

     This convenience function is equivalent to calling sceneRect().width().

     \sa height()
*/

/*!
     \fn qreal QGraphicsScene::height() const

     This convenience function is equivalent to calling \c sceneRect().height().

     \sa width()
*/

/*!
    Renders the \a source rect from scene into \a target, using \a painter. This
    function is useful for capturing the contents of the scene onto a paint
    device, such as a QImage (e.g., to take a screenshot), or for printing
    with QPrinter. For example:

    \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsscene.cpp 1

    If \a source is a null rect, this function will use sceneRect() to
    determine what to render. If \a target is a null rect, the dimensions of \a
    painter's paint device will be used.

    The source rect contents will be transformed according to \a
    aspectRatioMode to fit into the target rect. By default, the aspect ratio
    is kept, and \a source is scaled to fit in \a target.

    \sa QGraphicsView::render()
*/
void QGraphicsScene::render(QPainter *painter, const QRectF &target, const QRectF &source,
                            Qt::AspectRatioMode aspectRatioMode)
{
    // ### Switch to using the recursive rendering algorithm instead.

    // Default source rect = scene rect
    QRectF sourceRect = source;
    if (sourceRect.isNull())
        sourceRect = sceneRect();

    // Default target rect = device rect
    QRectF targetRect = target;
    if (targetRect.isNull()) {
        if (painter->device()->devType() == QInternal::Picture)
            targetRect = sourceRect;
        else
            targetRect.setRect(0, 0, painter->device()->width(), painter->device()->height());
    }

    // Find the ideal x / y scaling ratio to fit \a source into \a target.
    qreal xratio = targetRect.width() / sourceRect.width();
    qreal yratio = targetRect.height() / sourceRect.height();

    // Scale according to the aspect ratio mode.
    switch (aspectRatioMode) {
    case Qt::KeepAspectRatio:
        xratio = yratio = qMin(xratio, yratio);
        break;
    case Qt::KeepAspectRatioByExpanding:
        xratio = yratio = qMax(xratio, yratio);
        break;
    case Qt::IgnoreAspectRatio:
        break;
    }

    // Find all items to draw, and reverse the list (we want to draw
    // in reverse order).
    QList<QGraphicsItem *> itemList = items(sourceRect, Qt::IntersectsItemBoundingRect);
    QGraphicsItem **itemArray = new QGraphicsItem *[itemList.size()];
    int numItems = itemList.size();
    for (int i = 0; i < numItems; ++i)
        itemArray[numItems - i - 1] = itemList.at(i);
    itemList.clear();

    painter->save();

    // Transform the painter.
    painter->setClipRect(targetRect, Qt::IntersectClip);
    QTransform painterTransform;
    painterTransform *= QTransform()
                        .translate(targetRect.left(), targetRect.top())
                        .scale(xratio, yratio)
                        .translate(-sourceRect.left(), -sourceRect.top());
    painter->setWorldTransform(painterTransform, true);

    // Two unit vectors.
    QLineF v1(0, 0, 1, 0);
    QLineF v2(0, 0, 0, 1);

    // Generate the style options
    QStyleOptionGraphicsItem *styleOptionArray = new QStyleOptionGraphicsItem[numItems];
    for (int i = 0; i < numItems; ++i)
        itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], painterTransform, targetRect.toRect());

    // Render the scene.
    drawBackground(painter, sourceRect);
    drawItems(painter, numItems, itemArray, styleOptionArray);
    drawForeground(painter, sourceRect);

    delete [] itemArray;
    delete [] styleOptionArray;

    painter->restore();
}

/*!
    \property QGraphicsScene::itemIndexMethod
    \brief the item indexing method.

    QGraphicsScene applies an indexing algorithm to the scene, to speed up
    item discovery functions like items() and itemAt(). Indexing is most
    efficient for static scenes (i.e., where items don't move around). For
    dynamic scenes, or scenes with many animated items, the index bookkeeping
    can outweight the fast lookup speeds.

    For the common case, the default index method BspTreeIndex works fine.  If
    your scene uses many animations and you are experiencing slowness, you can
    disable indexing by calling \c setItemIndexMethod(NoIndex).

    \sa bspTreeDepth
*/
QGraphicsScene::ItemIndexMethod QGraphicsScene::itemIndexMethod() const
{
    Q_D(const QGraphicsScene);
    return d->indexMethod;
}
void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method)
{
    Q_D(QGraphicsScene);
    if (d->indexMethod == method)
        return;

    d->indexMethod = method;

    QList<QGraphicsItem *> oldItems = d->index->items(Qt::DescendingOrder);
    delete d->index;
    if (method == BspTreeIndex)
        d->index = new QGraphicsSceneBspTreeIndex(this);
    else
        d->index = new QGraphicsSceneLinearIndex(this);
    for (int i = oldItems.size() - 1; i >= 0; --i)
        d->index->addItem(oldItems.at(i));
}

/*!
    \property QGraphicsScene::bspTreeDepth
    \brief the depth of QGraphicsScene's BSP index tree
    \since 4.3

    This property has no effect when NoIndex is used.

    This value determines the depth of QGraphicsScene's BSP tree. The depth
    directly affects QGraphicsScene's performance and memory usage; the latter
    growing exponentially with the depth of the tree. With an optimal tree
    depth, QGraphicsScene can instantly determine the locality of items, even
    for scenes with thousands or millions of items. This also greatly improves
    rendering performance.

    By default, the value is 0, in which case Qt will guess a reasonable
    default depth based on the size, location and number of items in the
    scene. If these parameters change frequently, however, you may experience
    slowdowns as QGraphicsScene retunes the depth internally. You can avoid
    potential slowdowns by fixating the tree depth through setting this
    property.

    The depth of the tree and the size of the scene rectangle decide the
    granularity of the scene's partitioning. The size of each scene segment is
    determined by the following algorithm:

    \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsscene.cpp 2

    The BSP tree has an optimal size when each segment contains between 0 and
    10 items.

    \sa itemIndexMethod
*/
int QGraphicsScene::bspTreeDepth() const
{
    Q_D(const QGraphicsScene);
    QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex *>(d->index);
    return bspTree ? bspTree->bspTreeDepth() : 0;
}
void QGraphicsScene::setBspTreeDepth(int depth)
{
    Q_D(QGraphicsScene);
    if (depth < 0) {
        qWarning("QGraphicsScene::setBspTreeDepth: invalid depth %d ignored; must be >= 0", depth);
        return;
    }

    QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex *>(d->index);
    if (!bspTree) {
        qWarning("QGraphicsScene::setBspTreeDepth: can not apply if indexing method is not BSP");
        return;
    }
    bspTree->setBspTreeDepth(depth);
}

/*!
    \property QGraphicsScene::sortCacheEnabled
    \brief whether sort caching is enabled
    \since 4.5
    \obsolete

    Since Qt 4.6, this property has no effect.
*/
bool QGraphicsScene::isSortCacheEnabled() const
{
    Q_D(const QGraphicsScene);
    return d->sortCacheEnabled;
}
void QGraphicsScene::setSortCacheEnabled(bool enabled)
{
    Q_D(QGraphicsScene);
    if (d->sortCacheEnabled == enabled)
        return;
    d->sortCacheEnabled = enabled;
}

/*!
    Calculates and returns the bounding rect of all items on the scene. This
    function works by iterating over all items, and because if this, it can
    be slow for large scenes.

    \sa sceneRect()
*/
QRectF QGraphicsScene::itemsBoundingRect() const
{
    // Does not take untransformable items into account.
    QRectF boundingRect;
    foreach (QGraphicsItem *item, items())
        boundingRect |= item->sceneBoundingRect();
    return boundingRect;
}

/*!
    Returns a list of all items in the scene in descending stacking order.

    \sa addItem(), removeItem(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsScene::items() const
{
    Q_D(const QGraphicsScene);
    return d->index->items(Qt::DescendingOrder);
}

/*!
    Returns an ordered list of all items on the scene. \a order decides the
    stacking order.

    \sa addItem(), removeItem(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsScene::items(Qt::SortOrder order) const
{
    Q_D(const QGraphicsScene);
    return d->index->items(order);
}

/*!
    \obsolete

    Returns all visible items at position \a pos in the scene. The items are
    listed in descending stacking order (i.e., the first item in the list is the
    top-most item, and the last item is the bottom-most item).

    This function is deprecated and returns incorrect results if the scene
    contains items that ignore transformations. Use the overload that takes
    a QTransform instead.

    \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const
{
    Q_D(const QGraphicsScene);
    return d->index->items(pos, Qt::IntersectsItemShape, Qt::DescendingOrder);
}

/*!
    \overload
    \obsolete

    Returns all visible items that, depending on \a mode, are either inside or
    intersect with the specified \a rectangle.

    The default value for \a mode is Qt::IntersectsItemShape; all items whose
    exact shape intersects with or is contained by \a rectangle are returned.

    This function is deprecated and returns incorrect results if the scene
    contains items that ignore transformations. Use the overload that takes
    a QTransform instead.

    \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSelectionMode mode) const
{
    Q_D(const QGraphicsScene);
    return d->index->items(rectangle, mode, Qt::DescendingOrder);
}

/*!
    \fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode) const
    \obsolete
    \since 4.3

    This convenience function is equivalent to calling items(QRectF(\a x, \a y, \a w, \a h), \a mode).

    This function is deprecated and returns incorrect results if the scene
    contains items that ignore transformations. Use the overload that takes
    a QTransform instead.
*/

/*!
    \fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const
    \overload
    \since 4.6

    \brief Returns all visible items that, depending on \a mode, are
    either inside or intersect with the rectangle defined by \a x, \a y,
    \a w and \a h, in a list sorted using \a order.

    \a deviceTransform is the transformation that applies to the view, and needs to
    be provided if the scene contains items that ignore transformations.
*/

/*!
    \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode) const
    \overload
    \obsolete

    Returns all visible items that, depending on \a mode, are either inside or
    intersect with the polygon \a polygon.

    The default value for \a mode is Qt::IntersectsItemShape; all items whose
    exact shape intersects with or is contained by \a polygon are returned.

    This function is deprecated and returns incorrect results if the scene
    contains items that ignore transformations. Use the overload that takes
    a QTransform instead.

    \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode) const
{
    Q_D(const QGraphicsScene);
    return d->index->items(polygon, mode, Qt::DescendingOrder);
}

/*!
    \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const
    \overload
    \obsolete

    Returns all visible items that, depending on \a path, are either inside or
    intersect with the path \a path.

    The default value for \a mode is Qt::IntersectsItemShape; all items whose
    exact shape intersects with or is contained by \a path are returned.

    This function is deprecated and returns incorrect results if the scene
    contains items that ignore transformations. Use the overload that takes
    a QTransform instead.

    \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const
{
    Q_D(const QGraphicsScene);
    return d->index->items(path, mode, Qt::DescendingOrder);
}

/*!
    \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const
    \since 4.6

    \brief Returns all visible items that, depending on \a mode, are at
    the specified \a pos in a list sorted using \a order.

    The default value for \a mode is Qt::IntersectsItemShape; all items whose
    exact shape intersects with \a pos are returned.

    \a deviceTransform is the transformation that applies to the view, and needs to
    be provided if the scene contains items that ignore transformations.

    \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos, Qt::ItemSelectionMode mode,
                                             Qt::SortOrder order, const QTransform &deviceTransform) const
{
    Q_D(const QGraphicsScene);
    return d->index->items(pos, mode, order, deviceTransform);
}

/*!
    \fn QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const
    \overload
    \since 4.6

    \brief Returns all visible items that, depending on \a mode, are
    either inside or intersect with the specified \a rect and return a
    list sorted using \a order.

    The default value for \a mode is Qt::IntersectsItemShape; all items whose
    exact shape intersects with or is contained by \a rect are returned.

    \a deviceTransform is the transformation that applies to the view, and needs to
    be provided if the scene contains items that ignore transformations.

    \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode,
                                             Qt::SortOrder order, const QTransform &deviceTransform) const
{
    Q_D(const QGraphicsScene);
    return d->index->items(rect, mode, order, deviceTransform);
}

/*!
    \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const
    \overload
    \since 4.6

    \brief Returns all visible items that, depending on \a mode, are
    either inside or intersect with the specified \a polygon and return
    a list sorted using \a order.

    The default value for \a mode is Qt::IntersectsItemShape; all items whose
    exact shape intersects with or is contained by \a polygon are returned.

    \a deviceTransform is the transformation that applies to the view, and needs to
    be provided if the scene contains items that ignore transformations.

    \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode,
                                             Qt::SortOrder order, const QTransform &deviceTransform) const
{
    Q_D(const QGraphicsScene);
    return d->index->items(polygon, mode, order, deviceTransform);
}

/*!
    \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const
    \overload
    \since 4.6

    \brief Returns all visible items that, depending on \a mode, are
    either inside or intersect with the specified \a path and return a
    list sorted using \a order.

    The default value for \a mode is Qt::IntersectsItemShape; all items whose
    exact shape intersects with or is contained by \a path are returned.

    \a deviceTransform is the transformation that applies to the view, and needs to
    be provided if the scene contains items that ignore transformations.

    \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode,
                                             Qt::SortOrder order, const QTransform &deviceTransform) const
{
    Q_D(const QGraphicsScene);
    return d->index->items(path, mode, order, deviceTransform);
}

/*!
    Returns a list of all items that collide with \a item. Collisions are
    determined by calling QGraphicsItem::collidesWithItem(); the collision
    detection is determined by \a mode. By default, all items whose shape
    intersects \a item or is contained inside \a item's shape are returned.

    The items are returned in descending stacking order (i.e., the first item
    in the list is the uppermost item, and the last item is the lowermost
    item).

    \sa items(), itemAt(), QGraphicsItem::collidesWithItem(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsScene::collidingItems(const QGraphicsItem *item,
                                                      Qt::ItemSelectionMode mode) const
{
    Q_D(const QGraphicsScene);
    if (!item) {
        qWarning("QGraphicsScene::collidingItems: cannot find collisions for null item");
        return QList<QGraphicsItem *>();
    }

    // Does not support ItemIgnoresTransformations.
    QList<QGraphicsItem *> tmp;
    foreach (QGraphicsItem *itemInVicinity, d->index->estimateItems(item->sceneBoundingRect(), Qt::DescendingOrder)) {
        if (item != itemInVicinity && item->collidesWithItem(itemInVicinity, mode))
            tmp << itemInVicinity;
    }
    return tmp;
}

/*!
    \overload
    \obsolete

    Returns the topmost visible item at the specified \a position, or 0 if
    there are no items at this position.

    This function is deprecated and returns incorrect results if the scene
    contains items that ignore transformations. Use the overload that takes
    a QTransform instead.

    \sa items(), collidingItems(), {QGraphicsItem#Sorting}{Sorting}
*/
QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position) const
{
    QList<QGraphicsItem *> itemsAtPoint = items(position);
    return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first();
}

/*!
    \since 4.6

    Returns the topmost visible item at the specified \a position, or 0
    if there are no items at this position.

    \a deviceTransform is the transformation that applies to the view, and needs to
    be provided if the scene contains items that ignore transformations.

    \sa items(), collidingItems(), {QGraphicsItem#Sorting}{Sorting}
*/
QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position, const QTransform &deviceTransform) const
{
    QList<QGraphicsItem *> itemsAtPoint = items(position, Qt::IntersectsItemShape,
                                                Qt::DescendingOrder, deviceTransform);
    return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first();
}

/*!
    \fn QGraphicsScene::itemAt(qreal x, qreal y, const QTransform &deviceTransform) const
    \overload
    \since 4.6

    Returns the topmost item at the position specified by (\a x, \a
    y), or 0 if there are no items at this position.

    \a deviceTransform is the transformation that applies to the view, and needs to
    be provided if the scene contains items that ignore transformations.

    This convenience function is equivalent to calling \c
    {itemAt(QPointF(x, y), deviceTransform)}.
*/

/*!
    \fn QGraphicsScene::itemAt(qreal x, qreal y) const
    \overload
    \obsolete

    Returns the topmost item at the position specified by (\a x, \a
    y), or 0 if there are no items at this position.

    This convenience function is equivalent to calling \c
    {itemAt(QPointF(x, y))}.

    This function is deprecated and returns incorrect results if the scene
    contains items that ignore transformations. Use the overload that takes
    a QTransform instead.
*/

/*!
    Returns a list of all currently selected items. The items are
    returned in no particular order.

    \sa setSelectionArea()
*/
QList<QGraphicsItem *> QGraphicsScene::selectedItems() const
{
    Q_D(const QGraphicsScene);

    // Optimization: Lazily removes items that are not selected.
    QGraphicsScene *that = const_cast<QGraphicsScene *>(this);
    QSet<QGraphicsItem *> actuallySelectedSet;
    foreach (QGraphicsItem *item, that->d_func()->selectedItems) {
        if (item->isSelected())
            actuallySelectedSet << item;
    }

    that->d_func()->selectedItems = actuallySelectedSet;

    return d->selectedItems.values();
}

/*!
    Returns the selection area that was previously set with
    setSelectionArea(), or an empty QPainterPath if no selection area has been
    set.

    \sa setSelectionArea()
*/
QPainterPath QGraphicsScene::selectionArea() const
{
    Q_D(const QGraphicsScene);
    return d->selectionArea;
}

/*!
    \since 4.6

    Sets the selection area to \a path. All items within this area are
    immediately selected, and all items outside are unselected. You can get
    the list of all selected items by calling selectedItems().

    \a deviceTransform is the transformation that applies to the view, and needs to
    be provided if the scene contains items that ignore transformations.

    For an item to be selected, it must be marked as \e selectable
    (QGraphicsItem::ItemIsSelectable).

    \sa clearSelection(), selectionArea()
*/
void QGraphicsScene::setSelectionArea(const QPainterPath &path, const QTransform &deviceTransform)
{
    setSelectionArea(path, Qt::IntersectsItemShape, deviceTransform);
}

/*!
    \obsolete
    \overload

    Sets the selection area to \a path.

    This function is deprecated and leads to incorrect results if the scene
    contains items that ignore transformations. Use the overload that takes
    a QTransform instead.
*/
void QGraphicsScene::setSelectionArea(const QPainterPath &path)
{
    setSelectionArea(path, Qt::IntersectsItemShape, QTransform());
}

/*!
    \obsolete
    \overload
    \since 4.3

    Sets the selection area to \a path using \a mode to determine if items are
    included in the selection area.

    \sa clearSelection(), selectionArea()
*/
void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode)
{
    setSelectionArea(path, mode, QTransform());
}

/*!
    \overload
    \since 4.6

    Sets the selection area to \a path using \a mode to determine if items are
    included in the selection area.

    \a deviceTransform is the transformation that applies to the view, and needs to
    be provided if the scene contains items that ignore transformations.

    \sa clearSelection(), selectionArea()
*/
void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode,
                                      const QTransform &deviceTransform)
{
    Q_D(QGraphicsScene);

    // Note: with boolean path operations, we can improve performance here
    // quite a lot by "growing" the old path instead of replacing it. That
    // allows us to only check the intersect area for changes, instead of
    // reevaluating the whole path over again.
    d->selectionArea = path;

    QSet<QGraphicsItem *> unselectItems = d->selectedItems;

    // Disable emitting selectionChanged() for individual items.
    ++d->selectionChanging;
    bool changed = false;

    // Set all items in path to selected.
    foreach (QGraphicsItem *item, items(path, mode, Qt::DescendingOrder, deviceTransform)) {
        if (item->flags() & QGraphicsItem::ItemIsSelectable) {
            if (!item->isSelected())
                changed = true;
            unselectItems.remove(item);
            item->setSelected(true);
        }
    }

    // Unselect all items outside path.
    foreach (QGraphicsItem *item, unselectItems) {
        item->setSelected(false);
        changed = true;
    }

    // Reenable emitting selectionChanged() for individual items.
    --d->selectionChanging;

    if (!d->selectionChanging && changed)
        emit selectionChanged();
}

/*!
   Clears the current selection.

   \sa setSelectionArea(), selectedItems()
*/
void QGraphicsScene::clearSelection()
{
    Q_D(QGraphicsScene);

    // Disable emitting selectionChanged
    ++d->selectionChanging;
    bool changed = !d->selectedItems.isEmpty();

    foreach (QGraphicsItem *item, d->selectedItems)
        item->setSelected(false);
    d->selectedItems.clear();

    // Reenable emitting selectionChanged() for individual items.
    --d->selectionChanging;

    if (!d->selectionChanging && changed)
        emit selectionChanged();
}

/*!
    \since 4.4

    Removes and deletes all items from the scene, but otherwise leaves the
    state of the scene unchanged.

    \sa addItem()
*/
void QGraphicsScene::clear()
{
    Q_D(QGraphicsScene);
    // NB! We have to clear the index before deleting items; otherwise the
    // index might try to access dangling item pointers.
    d->index->clear();
    // NB! QGraphicsScenePrivate::unregisterTopLevelItem() removes items
    while (!d->topLevelItems.isEmpty())
        delete d->topLevelItems.first();
    Q_ASSERT(d->topLevelItems.isEmpty());
    d->lastItemCount = 0;
    d->allItemsIgnoreHoverEvents = true;
    d->allItemsUseDefaultCursor = true;
    d->allItemsIgnoreTouchEvents = true;
}

/*!
    Groups all items in \a items into a new QGraphicsItemGroup, and returns a
    pointer to the group. The group is created with the common ancestor of \a
    items as its parent, and with position (0, 0). The items are all
    reparented to the group, and their positions and transformations are
    mapped to the group. If \a items is empty, this function will return an
    empty top-level QGraphicsItemGroup.

    QGraphicsScene has ownership of the group item; you do not need to delete
    it. To dismantle (ungroup) a group, call destroyItemGroup().

    \sa destroyItemGroup(), QGraphicsItemGroup::addToGroup()
*/
QGraphicsItemGroup *QGraphicsScene::createItemGroup(const QList<QGraphicsItem *> &items)
{
    // Build a list of the first item's ancestors
    QList<QGraphicsItem *> ancestors;
    int n = 0;
    if (!items.isEmpty()) {
        QGraphicsItem *parent = items.at(n++);
        while ((parent = parent->parentItem()))
            ancestors.append(parent);
    }

    // Find the common ancestor for all items
    QGraphicsItem *commonAncestor = 0;
    if (!ancestors.isEmpty()) {
        while (n < items.size()) {
            int commonIndex = -1;
            QGraphicsItem *parent = items.at(n++);
            do {
                int index = ancestors.indexOf(parent, qMax(0, commonIndex));
                if (index != -1) {
                    commonIndex = index;
                    break;
                }
            } while ((parent = parent->parentItem()));

            if (commonIndex == -1) {
                commonAncestor = 0;
                break;
            }

            commonAncestor = ancestors.at(commonIndex);
        }
    }

    // Create a new group at that level
    QGraphicsItemGroup *group = new QGraphicsItemGroup(commonAncestor);
    if (!commonAncestor)
        addItem(group);
    foreach (QGraphicsItem *item, items)
        group->addToGroup(item);
    return group;
}

/*!
    Reparents all items in \a group to \a group's parent item, then removes \a
    group from the scene, and finally deletes it. The items' positions and
    transformations are mapped from the group to the group's parent.

    \sa createItemGroup(), QGraphicsItemGroup::removeFromGroup()
*/
void QGraphicsScene::destroyItemGroup(QGraphicsItemGroup *group)
{
    foreach (QGraphicsItem *item, group->children())
        group->removeFromGroup(item);
    removeItem(group);
    delete group;
}

/*!
    Adds or moves the \a item and all its childen to this scene.
    This scene takes ownership of the \a item.

    If the item is visible (i.e., QGraphicsItem::isVisible() returns
    true), QGraphicsScene will emit changed() once control goes back
    to the event loop.

    If the item is already in a different scene, it will first be
    removed from its old scene, and then added to this scene as a
    top-level.

    QGraphicsScene will send ItemSceneChange notifications to \a item
    while it is added to the scene. If item does not currently belong
    to a scene, only one notification is sent. If it does belong to
    scene already (i.e., it is moved to this scene), QGraphicsScene
    will send an addition notification as the item is removed from its
    previous scene.

    If the item is a panel, the scene is active, and there is no
    active panel in the scene, then the item will be activated.

    \sa removeItem(), addEllipse(), addLine(), addPath(), addPixmap(),
    addRect(), addText(), addWidget(), {QGraphicsItem#Sorting}{Sorting}
*/
void QGraphicsScene::addItem(QGraphicsItem *item)
{
    Q_D(QGraphicsScene);
    if (!item) {
        qWarning("QGraphicsScene::addItem: cannot add null item");
        return;
    }
    if (item->d_ptr->scene == this) {
        qWarning("QGraphicsScene::addItem: item has already been added to this scene");
        return;
    }
    // Remove this item from its existing scene
    if (QGraphicsScene *oldScene = item->d_ptr->scene)
        oldScene->removeItem(item);

    // Notify the item that its scene is changing, and allow the item to
    // react.
    const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange,
                                                    QVariant::fromValue<QGraphicsScene *>(this)));
    QGraphicsScene *targetScene = qvariant_cast<QGraphicsScene *>(newSceneVariant);
    if (targetScene != this) {
        if (targetScene && item->d_ptr->scene != targetScene)
            targetScene->addItem(item);
        return;
    }

    // QDeclarativeItems do not rely on initial itemChanged message, as the componentComplete
    // function allows far more opportunity for delayed-construction optimization.
    if (!item->d_ptr->isDeclarativeItem) {
        if (d->unpolishedItems.isEmpty()) {
            QMetaMethod method = metaObject()->method(d->polishItemsIndex);
            method.invoke(this, Qt::QueuedConnection);
        }
        d->unpolishedItems.append(item);
        item->d_ptr->pendingPolish = true;
    }

    // Detach this item from its parent if the parent's scene is different
    // from this scene.
    if (QGraphicsItem *itemParent = item->d_ptr->parent) {
        if (itemParent->d_ptr->scene != this)
            item->setParentItem(0);
    }

    // Add the item to this scene
    item->d_func()->scene = targetScene;

    // Add the item in the index
    d->index->addItem(item);

    // Add to list of toplevels if this item is a toplevel.
    if (!item->d_ptr->parent)
        d->registerTopLevelItem(item);

    // Add to list of items that require an update. We cannot assume that the
    // item is fully constructed, so calling item->update() can lead to a pure
    // virtual function call to boundingRect().
    d->markDirty(item);
    d->dirtyGrowingItemsBoundingRect = true;

    // Disable selectionChanged() for individual items
    ++d->selectionChanging;
    int oldSelectedItemSize = d->selectedItems.size();

    // Enable mouse tracking if the item accepts hover events or has a cursor set.
    if (d->allItemsIgnoreHoverEvents && d->itemAcceptsHoverEvents_helper(item)) {
        d->allItemsIgnoreHoverEvents = false;
        d->enableMouseTrackingOnViews();
    }
#ifndef QT_NO_CURSOR
    if (d->allItemsUseDefaultCursor && item->d_ptr->hasCursor) {
        d->allItemsUseDefaultCursor = false;
        if (d->allItemsIgnoreHoverEvents) // already enabled otherwise
            d->enableMouseTrackingOnViews();
    }
#endif //QT_NO_CURSOR

    // Enable touch events if the item accepts touch events.
    if (d->allItemsIgnoreTouchEvents && item->d_ptr->acceptTouchEvents) {
        d->allItemsIgnoreTouchEvents = false;
        d->enableTouchEventsOnViews();
    }

#ifndef QT_NO_GESTURES
    foreach (Qt::GestureType gesture, item->d_ptr->gestureContext.keys())
        d->grabGesture(item, gesture);
#endif

    // Update selection lists
    if (item->isSelected())
        d->selectedItems << item;
    if (item->isWidget() && item->isVisible() && static_cast<QGraphicsWidget *>(item)->windowType() == Qt::Popup)
        d->addPopup(static_cast<QGraphicsWidget *>(item));
    if (item->isPanel() && item->isVisible() && item->panelModality() != QGraphicsItem::NonModal)
        d->enterModal(item);

    // Update creation order focus chain. Make sure to leave the widget's
    // internal tab order intact.
    if (item->isWidget()) {
        QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
        if (!d->tabFocusFirst) {
            // No first tab focus widget - make this the first tab focus
            // widget.
            d->tabFocusFirst = widget;
        } else if (!widget->parentWidget()) {
            // Adding a widget that is not part of a tab focus chain.
            QGraphicsWidget *last = d->tabFocusFirst->d_func()->focusPrev;
            QGraphicsWidget *lastNew = widget->d_func()->focusPrev;
            last->d_func()->focusNext = widget;
            widget->d_func()->focusPrev = last;
            d->tabFocusFirst->d_func()->focusPrev = lastNew;
            lastNew->d_func()->focusNext = d->tabFocusFirst;
        }
    }

    // Add all children recursively
    item->d_ptr->ensureSortedChildren();
    for (int i = 0; i < item->d_ptr->children.size(); ++i)
        addItem(item->d_ptr->children.at(i));

    // Resolve font and palette.
    item->d_ptr->resolveFont(d->font.resolve());
    item->d_ptr->resolvePalette(d->palette.resolve());


    // Reenable selectionChanged() for individual items
    --d->selectionChanging;
    if (!d->selectionChanging && d->selectedItems.size() != oldSelectedItemSize)
        emit selectionChanged();

    // Deliver post-change notification
    item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant);

    // Update explicit activation
    bool autoActivate = true;
    if (!d->childExplicitActivation && item->d_ptr->explicitActivate)
        d->childExplicitActivation = item->d_ptr->wantsActive ? 1 : 2;
    if (d->childExplicitActivation && item->isPanel()) {
        if (d->childExplicitActivation == 1)
            setActivePanel(item);
        else
            autoActivate = false;
        d->childExplicitActivation = 0;
    } else if (!item->d_ptr->parent) {
        d->childExplicitActivation = 0;
    }

    // Auto-activate this item's panel if nothing else has been activated
    if (autoActivate) {
        if (!d->lastActivePanel && !d->activePanel && item->isPanel()) {
            if (isActive())
                setActivePanel(item);
            else
                d->lastActivePanel = item;
        }
    }

    if (item->d_ptr->flags & QGraphicsItem::ItemSendsScenePositionChanges)
        d->registerScenePosItem(item);

    // Ensure that newly added items that have subfocus set, gain
    // focus automatically if there isn't a focus item already.
    if (!d->focusItem && item != d->lastFocusItem && item->focusItem() == item)
        item->focusItem()->setFocus();

    d->updateInputMethodSensitivityInViews();
}

/*!
    Creates and adds an ellipse item to the scene, and returns the item
    pointer. The geometry of the ellipse is defined by \a rect, and its pen
    and brush are initialized to \a pen and \a brush.

    Note that the item's geometry is provided in item coordinates, and its
    position is initialized to (0, 0).

    If the item is visible (i.e., QGraphicsItem::isVisible() returns true),
    QGraphicsScene will emit changed() once control goes back to the event
    loop.

    \sa addLine(), addPath(), addPixmap(), addRect(), addText(), addItem(),
    addWidget()
*/
QGraphicsEllipseItem *QGraphicsScene::addEllipse(const QRectF &rect, const QPen &pen, const QBrush &brush)
{
    QGraphicsEllipseItem *item = new QGraphicsEllipseItem(rect);
    item->setPen(pen);
    item->setBrush(brush);
    addItem(item);
    return item;
}

/*!
    \fn QGraphicsEllipseItem *QGraphicsScene::addEllipse(qreal x, qreal y, qreal w, qreal h, const QPen &pen, const QBrush &brush)
    \since 4.3

    This convenience function is equivalent to calling addEllipse(QRectF(\a x,
    \a y, \a w, \a h), \a pen, \a brush).
*/

/*!
    Creates and adds a line item to the scene, and returns the item
    pointer. The geometry of the line is defined by \a line, and its pen
    is initialized to \a pen.

    Note that the item's geometry is provided in item coordinates, and its
    position is initialized to (0, 0).

    If the item is visible (i.e., QGraphicsItem::isVisible() returns true),
    QGraphicsScene will emit changed() once control goes back to the event
    loop.

    \sa addEllipse(), addPath(), addPixmap(), addRect(), addText(), addItem(),
    addWidget()
*/
QGraphicsLineItem *QGraphicsScene::addLine(const QLineF &line, const QPen &pen)
{
    QGraphicsLineItem *item = new QGraphicsLineItem(line);
    item->setPen(pen);
    addItem(item);
    return item;
}

/*!
    \fn QGraphicsLineItem *QGraphicsScene::addLine(qreal x1, qreal y1, qreal x2, qreal y2, const QPen &pen)
    \since 4.3

    This convenience function is equivalent to calling addLine(QLineF(\a x1,
    \a y1, \a x2, \a y2), \a pen).
*/

/*!
    Creates and adds a path item to the scene, and returns the item
    pointer. The geometry of the path is defined by \a path, and its pen and
    brush are initialized to \a pen and \a brush.

    Note that the item's geometry is provided in item coordinates, and its
    position is initialized to (0, 0).

    If the item is visible (i.e., QGraphicsItem::isVisible() returns true),
    QGraphicsScene will emit changed() once control goes back to the event
    loop.

    \sa addEllipse(), addLine(), addPixmap(), addRect(), addText(), addItem(),
    addWidget()
*/
QGraphicsPathItem *QGraphicsScene::addPath(const QPainterPath &path, const QPen &pen, const QBrush &brush)
{
    QGraphicsPathItem *item = new QGraphicsPathItem(path);
    item->setPen(pen);
    item->setBrush(brush);
    addItem(item);
    return item;
}

/*!
    Creates and adds a pixmap item to the scene, and returns the item
    pointer. The pixmap is defined by \a pixmap.

    Note that the item's geometry is provided in item coordinates, and its
    position is initialized to (0, 0).

    If the item is visible (i.e., QGraphicsItem::isVisible() returns true),
    QGraphicsScene will emit changed() once control goes back to the event
    loop.

    \sa addEllipse(), addLine(), addPath(), addRect(), addText(), addItem(),
    addWidget()
*/
QGraphicsPixmapItem *QGraphicsScene::addPixmap(const QPixmap &pixmap)
{
    QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap);
    addItem(item);
    return item;
}

/*!
    Creates and adds a polygon item to the scene, and returns the item
    pointer. The polygon is defined by \a polygon, and its pen and
    brush are initialized to \a pen and \a brush.

    Note that the item's geometry is provided in item coordinates, and its
    position is initialized to (0, 0).

    If the item is visible (i.e., QGraphicsItem::isVisible() returns true),
    QGraphicsScene will emit changed() once control goes back to the event
    loop.

    \sa addEllipse(), addLine(), addPath(), addRect(), addText(), addItem(),
    addWidget()
*/
QGraphicsPolygonItem *QGraphicsScene::addPolygon(const QPolygonF &polygon,
                                                 const QPen &pen, const QBrush &brush)
{
    QGraphicsPolygonItem *item = new QGraphicsPolygonItem(polygon);
    item->setPen(pen);
    item->setBrush(brush);
    addItem(item);
    return item;
}

/*!
    Creates and adds a rectangle item to the scene, and returns the item
    pointer. The geometry of the rectangle is defined by \a rect, and its pen
    and brush are initialized to \a pen and \a brush.

    Note that the item's geometry is provided in item coordinates, and its
    position is initialized to (0, 0). For example, if a QRect(50, 50, 100,
    100) is added, its top-left corner will be at (50, 50) relative to the
    origin in the items coordinate system.

    If the item is visible (i.e., QGraphicsItem::isVisible() returns true),
    QGraphicsScene will emit changed() once control goes back to the event
    loop.

    \sa addEllipse(), addLine(), addPixmap(), addPixmap(), addText(),
    addItem(), addWidget()
*/
QGraphicsRectItem *QGraphicsScene::addRect(const QRectF &rect, const QPen &pen, const QBrush &brush)
{
    QGraphicsRectItem *item = new QGraphicsRectItem(rect);
    item->setPen(pen);
    item->setBrush(brush);
    addItem(item);
    return item;
}

/*!
    \fn QGraphicsRectItem *QGraphicsScene::addRect(qreal x, qreal y, qreal w, qreal h, const QPen &pen, const QBrush &brush)
    \since 4.3

    This convenience function is equivalent to calling addRect(QRectF(\a x,
    \a y, \a w, \a h), \a pen, \a brush).
*/

/*!
    Creates and adds a text item to the scene, and returns the item
    pointer. The text string is initialized to \a text, and its font
    is initialized to \a font.

    The item's position is initialized to (0, 0).

    If the item is visible (i.e., QGraphicsItem::isVisible() returns true),
    QGraphicsScene will emit changed() once control goes back to the event
    loop.

    \sa addEllipse(), addLine(), addPixmap(), addPixmap(), addRect(),
    addItem(), addWidget()
*/
QGraphicsTextItem *QGraphicsScene::addText(const QString &text, const QFont &font)
{
    QGraphicsTextItem *item = new QGraphicsTextItem(text);
    item->setFont(font);
    addItem(item);
    return item;
}

/*!
    Creates and adds a QGraphicsSimpleTextItem to the scene, and returns the
    item pointer. The text string is initialized to \a text, and its font is
    initialized to \a font.

    The item's position is initialized to (0, 0).

    If the item is visible (i.e., QGraphicsItem::isVisible() returns true),
    QGraphicsScene will emit changed() once control goes back to the event
    loop.

    \sa addEllipse(), addLine(), addPixmap(), addPixmap(), addRect(),
    addItem(), addWidget()
*/
QGraphicsSimpleTextItem *QGraphicsScene::addSimpleText(const QString &text, const QFont &font)
{
    QGraphicsSimpleTextItem *item = new QGraphicsSimpleTextItem(text);
    item->setFont(font);
    addItem(item);
    return item;
}

/*!
    Creates a new QGraphicsProxyWidget for \a widget, adds it to the scene,
    and returns a pointer to the proxy. \a wFlags set the default window flags
    for the embedding proxy widget.

    The item's position is initialized to (0, 0).

    If the item is visible (i.e., QGraphicsItem::isVisible() returns true),
    QGraphicsScene will emit changed() once control goes back to the event
    loop.

    Note that widgets with the Qt::WA_PaintOnScreen widget attribute
    set and widgets that wrap an external application or controller
    are not supported. Examples are QGLWidget and QAxWidget.

    \sa addEllipse(), addLine(), addPixmap(), addPixmap(), addRect(),
    addText(), addSimpleText(), addItem()
*/
QGraphicsProxyWidget *QGraphicsScene::addWidget(QWidget *widget, Qt::WindowFlags wFlags)
{
    QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(0, wFlags);
    proxy->setWidget(widget);
    addItem(proxy);
    return proxy;
}

/*!
    Removes the item \a item and all its children from the scene.  The
    ownership of \a item is passed on to the caller (i.e.,
    QGraphicsScene will no longer delete \a item when destroyed).

    \sa addItem()
*/
void QGraphicsScene::removeItem(QGraphicsItem *item)
{
    // ### Refactoring: This function shares much functionality with _q_removeItemLater()
    Q_D(QGraphicsScene);
    if (!item) {
        qWarning("QGraphicsScene::removeItem: cannot remove 0-item");
        return;
    }
    if (item->scene() != this) {
        qWarning("QGraphicsScene::removeItem: item %p's scene (%p)"
                 " is different from this scene (%p)",
                 item, item->scene(), this);
        return;
    }

    // Notify the item that it's scene is changing to 0, allowing the item to
    // react.
    const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange,
                                                    QVariant::fromValue<QGraphicsScene *>(0)));
    QGraphicsScene *targetScene = qvariant_cast<QGraphicsScene *>(newSceneVariant);
    if (targetScene != 0 && targetScene != this) {
        targetScene->addItem(item);
        return;
    }

    d->removeItemHelper(item);

    // Deliver post-change notification
    item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant);

    d->updateInputMethodSensitivityInViews();
}

/*!
    When the scene is active, this functions returns the scene's current focus
    item, or 0 if no item currently has focus. When the scene is inactive, this
    functions returns the item that will gain input focus when the scene becomes
    active.

    The focus item receives keyboard input when the scene receives a
    key event.

    \sa setFocusItem(), QGraphicsItem::hasFocus(), isActive()
*/
QGraphicsItem *QGraphicsScene::focusItem() const
{
    Q_D(const QGraphicsScene);
    return isActive() ? d->focusItem : d->passiveFocusItem;
}

/*!
    Sets the scene's focus item to \a item, with the focus reason \a
    focusReason, after removing focus from any previous item that may have had
    focus.

    If \a item is 0, or if it either does not accept focus (i.e., it does not
    have the QGraphicsItem::ItemIsFocusable flag enabled), or is not visible
    or not enabled, this function only removes focus from any previous
    focusitem.

    If item is not 0, and the scene does not currently have focus (i.e.,
    hasFocus() returns false), this function will call setFocus()
    automatically.

    \sa focusItem(), hasFocus(), setFocus()
*/
void QGraphicsScene::setFocusItem(QGraphicsItem *item, Qt::FocusReason focusReason)
{
    Q_D(QGraphicsScene);
    if (item)
        item->setFocus(focusReason);
    else
        d->setFocusItemHelper(item, focusReason);
}

/*!
    Returns true if the scene has focus; otherwise returns false. If the scene
    has focus, it will will forward key events from QKeyEvent to any item that
    has focus.

    \sa setFocus(), setFocusItem()
*/
bool QGraphicsScene::hasFocus() const
{
    Q_D(const QGraphicsScene);
    return d->hasFocus;
}

/*!
    Sets focus on the scene by sending a QFocusEvent to the scene, passing \a
    focusReason as the reason. If the scene regains focus after having
    previously lost it while an item had focus, the last focus item will
    receive focus with \a focusReason as the reason.

    If the scene already has focus, this function does nothing.

    \sa hasFocus(), clearFocus(), setFocusItem()
*/
void QGraphicsScene::setFocus(Qt::FocusReason focusReason)
{
    Q_D(QGraphicsScene);
    if (d->hasFocus || !isActive())
        return;
    QFocusEvent event(QEvent::FocusIn, focusReason);
    QCoreApplication::sendEvent(this, &event);
}

/*!
    Clears focus from the scene. If any item has focus when this function is
    called, it will lose focus, and regain focus again once the scene regains
    focus.

    A scene that does not have focus ignores key events.

    \sa hasFocus(), setFocus(), setFocusItem()
*/
void QGraphicsScene::clearFocus()
{
    Q_D(QGraphicsScene);
    if (d->hasFocus) {
        d->hasFocus = false;
        d->passiveFocusItem = d->focusItem;
        setFocusItem(0, Qt::OtherFocusReason);
    }
}

/*!
    \property QGraphicsScene::stickyFocus
    \brief whether clicking into the scene background will clear focus

    \since 4.6

    In a QGraphicsScene with stickyFocus set to true, focus will remain
    unchanged when the user clicks into the scene background or on an item
    that does not accept focus. Otherwise, focus will be cleared.

    By default, this property is false.

    Focus changes in response to a mouse press. You can reimplement
    mousePressEvent() in a subclass of QGraphicsScene to toggle this property
    based on where the user has clicked.

    \sa clearFocus(), setFocusItem()
*/
void QGraphicsScene::setStickyFocus(bool enabled)
{
    Q_D(QGraphicsScene);
    d->stickyFocus = enabled;
}
bool QGraphicsScene::stickyFocus() const
{
    Q_D(const QGraphicsScene);
    return d->stickyFocus;
}

/*!
    Returns the current mouse grabber item, or 0 if no item is currently
    grabbing the mouse. The mouse grabber item is the item that receives all
    mouse events sent to the scene.

    An item becomes a mouse grabber when it receives and accepts a
    mouse press event, and it stays the mouse grabber until either of
    the following events occur:

    \list
    \o If the item receives a mouse release event when there are no other
    buttons pressed, it loses the mouse grab.
    \o If the item becomes invisible (i.e., someone calls \c {item->setVisible(false)}),
    or if it becomes disabled (i.e., someone calls \c {item->setEnabled(false)}),
    it loses the mouse grab.
    \o If the item is removed from the scene, it loses the mouse grab.
    \endlist

    If the item loses its mouse grab, the scene will ignore all mouse events
    until a new item grabs the mouse (i.e., until a new item receives a mouse
    press event).
*/
QGraphicsItem *QGraphicsScene::mouseGrabberItem() const
{
    Q_D(const QGraphicsScene);
    return !d->mouseGrabberItems.isEmpty() ? d->mouseGrabberItems.last() : 0;
}

/*!
    \property QGraphicsScene::backgroundBrush
    \brief the background brush of the scene.

    Set this property to changes the scene's background to a different color,
    gradient or texture. The default background brush is Qt::NoBrush. The
    background is drawn before (behind) the items.

    Example:

    \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsscene.cpp 3

    QGraphicsScene::render() calls drawBackground() to draw the scene
    background. For more detailed control over how the background is drawn,
    you can reimplement drawBackground() in a subclass of QGraphicsScene.
*/
QBrush QGraphicsScene::backgroundBrush() const
{
    Q_D(const QGraphicsScene);
    return d->backgroundBrush;
}
void QGraphicsScene::setBackgroundBrush(const QBrush &brush)
{
    Q_D(QGraphicsScene);
    d->backgroundBrush = brush;
    foreach (QGraphicsView *view, d->views) {
        view->resetCachedContent();
        view->viewport()->update();
    }
    update();
}

/*!
    \property QGraphicsScene::foregroundBrush
    \brief the foreground brush of the scene.

    Change this property to set the scene's foreground to a different
    color, gradient or texture.

    The foreground is drawn after (on top of) the items. The default
    foreground brush is Qt::NoBrush ( i.e. the foreground is not
    drawn).

    Example:

    \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsscene.cpp 4

    QGraphicsScene::render() calls drawForeground() to draw the scene
    foreground. For more detailed control over how the foreground is
    drawn, you can reimplement the drawForeground() function in a
    QGraphicsScene subclass.
*/
QBrush QGraphicsScene::foregroundBrush() const
{
    Q_D(const QGraphicsScene);
    return d->foregroundBrush;
}
void QGraphicsScene::setForegroundBrush(const QBrush &brush)
{
    Q_D(QGraphicsScene);
    d->foregroundBrush = brush;
    foreach (QGraphicsView *view, views())
        view->viewport()->update();
    update();
}

/*!
    This method is used by input methods to query a set of properties of
    the scene to be able to support complex input method operations as support
    for surrounding text and reconversions.

    The \a query parameter specifies which property is queried.

    \sa QWidget::inputMethodQuery()
*/
QVariant QGraphicsScene::inputMethodQuery(Qt::InputMethodQuery query) const
{
    Q_D(const QGraphicsScene);
    if (!d->focusItem || !(d->focusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod))
        return QVariant();
    const QTransform matrix = d->focusItem->sceneTransform();
    QVariant value = d->focusItem->inputMethodQuery(query);
    if (value.type() == QVariant::RectF)
        value = matrix.mapRect(value.toRectF());
    else if (value.type() == QVariant::PointF)
        value = matrix.map(value.toPointF());
    else if (value.type() == QVariant::Rect)
        value = matrix.mapRect(value.toRect());
    else if (value.type() == QVariant::Point)
        value = matrix.map(value.toPoint());
    return value;
}

/*!
    \fn void QGraphicsScene::update(const QRectF &rect)
    Schedules a redraw of the area \a rect on the scene.

    \sa sceneRect(), changed()
*/
void QGraphicsScene::update(const QRectF &rect)
{
    Q_D(QGraphicsScene);
    if (d->updateAll || (rect.isEmpty() && !rect.isNull()))
        return;

    // Check if anyone's connected; if not, we can send updates directly to
    // the views. Otherwise or if there are no views, use old behavior.
    bool directUpdates = !(d->isSignalConnected(d->changedSignalIndex)) && !d->views.isEmpty();
    if (rect.isNull()) {
        d->updateAll = true;
        d->updatedRects.clear();
        if (directUpdates) {
            // Update all views.
            for (int i = 0; i < d->views.size(); ++i)
                d->views.at(i)->d_func()->fullUpdatePending = true;
        }
    } else {
        if (directUpdates) {
            // Update all views.
            for (int i = 0; i < d->views.size(); ++i) {
                QGraphicsView *view = d->views.at(i);
                if (view->isTransformed())
                    view->d_func()->updateRectF(view->viewportTransform().mapRect(rect));
                else
                    view->d_func()->updateRectF(rect);
            }
        } else {
            d->updatedRects << rect;
        }
    }

    if (!d->calledEmitUpdated) {
        d->calledEmitUpdated = true;
        QMetaObject::invokeMethod(this, "_q_emitUpdated", Qt::QueuedConnection);
    }
}

/*!
    \fn void QGraphicsScene::update(qreal x, qreal y, qreal w, qreal h)
    \overload
    \since 4.3

    This function is equivalent to calling update(QRectF(\a x, \a y, \a w,
    \a h));
*/

/*!
    Invalidates and schedules a redraw of the \a layers in \a rect on the
    scene. Any cached content in \a layers is unconditionally invalidated and
    redrawn.

    You can use this function overload to notify QGraphicsScene of changes to
    the background or the foreground of the scene. This function is commonly
    used for scenes with tile-based backgrounds to notify changes when
    QGraphicsView has enabled
    \l{QGraphicsView::CacheBackground}{CacheBackground}.

    Example:

    \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsscene.cpp 5

    Note that QGraphicsView currently supports background caching only (see
    QGraphicsView::CacheBackground). This function is equivalent to calling
    update() if any layer but BackgroundLayer is passed.

    \sa QGraphicsView::resetCachedContent()
*/
void QGraphicsScene::invalidate(const QRectF &rect, SceneLayers layers)
{
    foreach (QGraphicsView *view, views())
        view->invalidateScene(rect, layers);
    update(rect);
}

/*!
    \fn void QGraphicsScene::invalidate(qreal x, qreal y, qreal w, qreal h, SceneLayers layers)
    \overload
    \since 4.3

    This convenience function is equivalent to calling invalidate(QRectF(\a x, \a
    y, \a w, \a h), \a layers);
*/

/*!
    Returns a list of all the views that display this scene.

    \sa QGraphicsView::scene()
*/
QList <QGraphicsView *> QGraphicsScene::views() const
{
    Q_D(const QGraphicsScene);
    return d->views;
}

/*!
    This slot \e advances the scene by one step, by calling
    QGraphicsItem::advance() for all items on the scene. This is done in two
    phases: in the first phase, all items are notified that the scene is about
    to change, and in the second phase all items are notified that they can
    move. In the first phase, QGraphicsItem::advance() is called passing a
    value of 0 as an argument, and 1 is passed in the second phase.

    \sa QGraphicsItem::advance(), QGraphicsItemAnimation, QTimeLine
*/
void QGraphicsScene::advance()
{
    for (int i = 0; i < 2; ++i) {
        foreach (QGraphicsItem *item, items())
            item->advance(i);
    }
}

/*!
    Processes the event \a event, and dispatches it to the respective
    event handlers.

    In addition to calling the convenience event handlers, this
    function is responsible for converting mouse move events to hover
    events for when there is no mouse grabber item. Hover events are
    delivered directly to items; there is no convenience function for
    them.

    Unlike QWidget, QGraphicsScene does not have the convenience functions
    \l{QWidget::}{enterEvent()} and \l{QWidget::}{leaveEvent()}. Use this
    function to obtain those events instead.

    \sa contextMenuEvent(), keyPressEvent(), keyReleaseEvent(),
    mousePressEvent(), mouseMoveEvent(), mouseReleaseEvent(),
    mouseDoubleClickEvent(), focusInEvent(), focusOutEvent()
*/
bool QGraphicsScene::event(QEvent *event)
{
    Q_D(QGraphicsScene);

    switch (event->type()) {
    case QEvent::GraphicsSceneMousePress:
    case QEvent::GraphicsSceneMouseMove:
    case QEvent::GraphicsSceneMouseRelease:
    case QEvent::GraphicsSceneMouseDoubleClick:
    case QEvent::GraphicsSceneHoverEnter:
    case QEvent::GraphicsSceneHoverLeave:
    case QEvent::GraphicsSceneHoverMove:
    case QEvent::TouchBegin:
    case QEvent::TouchUpdate:
    case QEvent::TouchEnd:
        // Reset the under-mouse list to ensure that this event gets fresh
        // item-under-mouse data. Be careful about this list; if people delete
        // items from inside event handlers, this list can quickly end up
        // having stale pointers in it. We need to clear it before dispatching
        // events that use it.
        // ### this should only be cleared if we received a new mouse move event,
        // which relies on us fixing the replay mechanism in QGraphicsView.
        d->cachedItemsUnderMouse.clear();
    default:
        break;
    }

    switch (event->type()) {
    case QEvent::GraphicsSceneDragEnter:
        dragEnterEvent(static_cast<QGraphicsSceneDragDropEvent *>(event));
        break;
    case QEvent::GraphicsSceneDragMove:
        dragMoveEvent(static_cast<QGraphicsSceneDragDropEvent *>(event));
        break;
    case QEvent::GraphicsSceneDragLeave:
        dragLeaveEvent(static_cast<QGraphicsSceneDragDropEvent *>(event));
        break;
    case QEvent::GraphicsSceneDrop:
        dropEvent(static_cast<QGraphicsSceneDragDropEvent *>(event));
        break;
    case QEvent::GraphicsSceneContextMenu:
        contextMenuEvent(static_cast<QGraphicsSceneContextMenuEvent *>(event));
        break;
    case QEvent::KeyPress:
        if (!d->focusItem) {
            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?
                    bool res = false;
                    if (k->key() == Qt::Key_Backtab
                        || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier))) {
                        res = focusNextPrevChild(false);
                    } else if (k->key() == Qt::Key_Tab) {
                        res = focusNextPrevChild(true);
                    }
                    if (!res)
                        event->ignore();
                    return true;
                }
            }
        }
        keyPressEvent(static_cast<QKeyEvent *>(event));
        break;
    case QEvent::KeyRelease:
        keyReleaseEvent(static_cast<QKeyEvent *>(event));
        break;
    case QEvent::ShortcutOverride: {
            QGraphicsItem *parent = focusItem();
            while (parent) {
                d->sendEvent(parent, event);
                if (event->isAccepted())
                    return true;
                parent = parent->parentItem();
            }
        }
        return false;
    case QEvent::GraphicsSceneMouseMove:
    {
        QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent *>(event);
        d->lastSceneMousePos = mouseEvent->scenePos();
        mouseMoveEvent(mouseEvent);
        break;
    }
    case QEvent::GraphicsSceneMousePress:
        mousePressEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
        break;
    case QEvent::GraphicsSceneMouseRelease:
        mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
        break;
    case QEvent::GraphicsSceneMouseDoubleClick:
        mouseDoubleClickEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
        break;
    case QEvent::GraphicsSceneWheel:
        wheelEvent(static_cast<QGraphicsSceneWheelEvent *>(event));
        break;
    case QEvent::FocusIn:
        focusInEvent(static_cast<QFocusEvent *>(event));
        break;
    case QEvent::FocusOut:
        focusOutEvent(static_cast<QFocusEvent *>(event));
        break;
    case QEvent::GraphicsSceneHoverEnter:
    case QEvent::GraphicsSceneHoverLeave:
    case QEvent::GraphicsSceneHoverMove:
    {
        QGraphicsSceneHoverEvent *hoverEvent = static_cast<QGraphicsSceneHoverEvent *>(event);
        d->lastSceneMousePos = hoverEvent->scenePos();
        d->dispatchHoverEvent(hoverEvent);
        break;
    }
    case QEvent::Leave:
        // hackieshly unpacking the viewport pointer from the leave event.
        d->leaveScene(reinterpret_cast<QWidget *>(event->d));
        break;
    case QEvent::GraphicsSceneHelp:
        helpEvent(static_cast<QGraphicsSceneHelpEvent *>(event));
        break;
    case QEvent::InputMethod:
        inputMethodEvent(static_cast<QInputMethodEvent *>(event));
        break;
    case QEvent::WindowActivate:
        if (!d->activationRefCount++) {
            if (d->lastActivePanel) {
                // Activate the last panel.
                d->setActivePanelHelper(d->lastActivePanel, true);
            } else if (d->tabFocusFirst && d->tabFocusFirst->isPanel()) {
                // Activate the panel of the first item in the tab focus
                // chain.
                d->setActivePanelHelper(d->tabFocusFirst, true);
            } else {
                // Activate all toplevel items.
                QEvent event(QEvent::WindowActivate);
                foreach (QGraphicsItem *item, items()) {
                    if (item->isVisible() && !item->isPanel() && !item->parentItem())
                        sendEvent(item, &event);
                }
            }
        }
        break;
    case QEvent::WindowDeactivate:
        if (!--d->activationRefCount) {
            if (d->activePanel) {
                // Deactivate the active panel (but keep it so we can
                // reactivate it later).
                QGraphicsItem *lastActivePanel = d->activePanel;
                d->setActivePanelHelper(0, true);
                d->lastActivePanel = lastActivePanel;
            } else {
                // Activate all toplevel items.
                QEvent event(QEvent::WindowDeactivate);
                foreach (QGraphicsItem *item, items()) {
                    if (item->isVisible() && !item->isPanel() && !item->parentItem())
                        sendEvent(item, &event);
                }
            }
        }
        break;
    case QEvent::ApplicationFontChange: {
        // Resolve the existing scene font.
        d->resolveFont();
        break;
    }
    case QEvent::FontChange:
        // Update the entire scene when the font changes.
        update();
        break;
    case QEvent::ApplicationPaletteChange: {
        // Resolve the existing scene palette.
        d->resolvePalette();
        break;
    }
    case QEvent::PaletteChange:
        // Update the entire scene when the palette changes.
        update();
        break;
    case QEvent::StyleChange:
        // Reresolve all widgets' styles. Update all top-level widgets'
        // geometries that do not have an explicit style set.
        update();
        break;
    case QEvent::TouchBegin:
    case QEvent::TouchUpdate:
    case QEvent::TouchEnd:
        d->touchEventHandler(static_cast<QTouchEvent *>(event));
        break;
#ifndef QT_NO_GESTURES
    case QEvent::Gesture:
    case QEvent::GestureOverride:
        d->gestureEventHandler(static_cast<QGestureEvent *>(event));
        break;
#endif // QT_NO_GESTURES
    default:
        return QObject::event(event);
    }
    return true;
}

/*!
    \reimp

    QGraphicsScene filters QApplication's events to detect palette and font
    changes.
*/
bool QGraphicsScene::eventFilter(QObject *watched, QEvent *event)
{
    if (watched != qApp)
        return false;

    switch (event->type()) {
    case QEvent::ApplicationPaletteChange:
        QApplication::postEvent(this, new QEvent(QEvent::ApplicationPaletteChange));
        break;
    case QEvent::ApplicationFontChange:
        QApplication::postEvent(this, new QEvent(QEvent::ApplicationFontChange));
        break;
    default:
        break;
    }
    return false;
}

/*!
    This event handler, for event \a contextMenuEvent, can be reimplemented in
    a subclass to receive context menu events. The default implementation
    forwards the event to the topmost item that accepts context menu events at
    the position of the event. If no items accept context menu events at this
    position, the event is ignored.

    \sa QGraphicsItem::contextMenuEvent()
*/
void QGraphicsScene::contextMenuEvent(QGraphicsSceneContextMenuEvent *contextMenuEvent)
{
    Q_D(QGraphicsScene);
    // Ignore by default.
    contextMenuEvent->ignore();

    // Send the event to all items at this position until one item accepts the
    // event.
    foreach (QGraphicsItem *item, d->itemsAtPosition(contextMenuEvent->screenPos(),
                                                     contextMenuEvent->scenePos(),
                                                     contextMenuEvent->widget())) {
        contextMenuEvent->setPos(item->d_ptr->genericMapFromScene(contextMenuEvent->scenePos(),
                                                                  contextMenuEvent->widget()));
        contextMenuEvent->accept();
        if (!d->sendEvent(item, contextMenuEvent))
            break;

        if (contextMenuEvent->isAccepted())
            break;
    }
}

/*!
    This event handler, for event \a event, can be reimplemented in a subclass
    to receive drag enter events for the scene.

    The default implementation accepts the event and prepares the scene to
    accept drag move events.

    \sa QGraphicsItem::dragEnterEvent(), dragMoveEvent(), dragLeaveEvent(),
    dropEvent()
*/
void QGraphicsScene::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
    Q_D(QGraphicsScene);
    d->dragDropItem = 0;
    d->lastDropAction = Qt::IgnoreAction;
    event->accept();
}

/*!
    This event handler, for event \a event, can be reimplemented in a subclass
    to receive drag move events for the scene.

    \sa QGraphicsItem::dragMoveEvent(), dragEnterEvent(), dragLeaveEvent(),
    dropEvent()
*/
void QGraphicsScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
{
    Q_D(QGraphicsScene);
    event->ignore();

    if (!d->mouseGrabberItems.isEmpty()) {
        // Mouse grabbers that start drag events lose the mouse grab.
        d->clearMouseGrabber();
        d->mouseGrabberButtonDownPos.clear();
        d->mouseGrabberButtonDownScenePos.clear();
        d->mouseGrabberButtonDownScreenPos.clear();
    }

    bool eventDelivered = false;

    // Find the topmost enabled items under the cursor. They are all
    // candidates for accepting drag & drop events.
    foreach (QGraphicsItem *item, d->itemsAtPosition(event->screenPos(),
                                                     event->scenePos(),
                                                     event->widget())) {
        if (!item->isEnabled() || !item->acceptDrops())
            continue;

        if (item != d->dragDropItem) {
            // Enter the new drag drop item. If it accepts the event, we send
            // the leave to the parent item.
            QGraphicsSceneDragDropEvent dragEnter(QEvent::GraphicsSceneDragEnter);
            d->cloneDragDropEvent(&dragEnter, event);
            dragEnter.setDropAction(event->proposedAction());
            d->sendDragDropEvent(item, &dragEnter);
            event->setAccepted(dragEnter.isAccepted());
            event->setDropAction(dragEnter.dropAction());
            if (!event->isAccepted()) {
                // Propagate to the item under
                continue;
            }

            d->lastDropAction = event->dropAction();

            if (d->dragDropItem) {
                // Leave the last drag drop item. A perfect implementation
                // would set the position of this event to the point where
                // this event and the last event intersect with the item's
                // shape, but that's not easy to do. :-)
                QGraphicsSceneDragDropEvent dragLeave(QEvent::GraphicsSceneDragLeave);
                d->cloneDragDropEvent(&dragLeave, event);
                d->sendDragDropEvent(d->dragDropItem, &dragLeave);
            }

            // We've got a new drag & drop item
            d->dragDropItem = item;
        }

        // Send the move event.
        event->setDropAction(d->lastDropAction);
        event->accept();
        d->sendDragDropEvent(item, event);
        if (event->isAccepted())
            d->lastDropAction = event->dropAction();
        eventDelivered = true;
        break;
    }

    if (!eventDelivered) {
        if (d->dragDropItem) {
            // Leave the last drag drop item
            QGraphicsSceneDragDropEvent dragLeave(QEvent::GraphicsSceneDragLeave);
            d->cloneDragDropEvent(&dragLeave, event);
            d->sendDragDropEvent(d->dragDropItem, &dragLeave);
            d->dragDropItem = 0;
        }
        // Propagate
        event->setDropAction(Qt::IgnoreAction);
    }
}

/*!
    This event handler, for event \a event, can be reimplemented in a subclass
    to receive drag leave events for the scene.

    \sa QGraphicsItem::dragLeaveEvent(), dragEnterEvent(), dragMoveEvent(),
    dropEvent()
*/
void QGraphicsScene::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
{
    Q_D(QGraphicsScene);
    if (d->dragDropItem) {
        // Leave the last drag drop item
        d->sendDragDropEvent(d->dragDropItem, event);
        d->dragDropItem = 0;
    }
}

/*!
    This event handler, for event \a event, can be reimplemented in a subclass
    to receive drop events for the scene.

    \sa QGraphicsItem::dropEvent(), dragEnterEvent(), dragMoveEvent(),
    dragLeaveEvent()
*/
void QGraphicsScene::dropEvent(QGraphicsSceneDragDropEvent *event)
{
    Q_UNUSED(event);
    Q_D(QGraphicsScene);
    if (d->dragDropItem) {
        // Drop on the last drag drop item
        d->sendDragDropEvent(d->dragDropItem, event);
        d->dragDropItem = 0;
    }
}

/*!
    This event handler, for event \a focusEvent, can be reimplemented in a
    subclass to receive focus in events.

    The default implementation sets focus on the scene, and then on the last
    focus item.

    \sa QGraphicsItem::focusOutEvent()
*/
void QGraphicsScene::focusInEvent(QFocusEvent *focusEvent)
{
    Q_D(QGraphicsScene);

    d->hasFocus = true;
    switch (focusEvent->reason()) {
    case Qt::TabFocusReason:
        if (!focusNextPrevChild(true))
            focusEvent->ignore();
        break;
    case Qt::BacktabFocusReason:
        if (!focusNextPrevChild(false))
            focusEvent->ignore();
        break;
    default:
        if (d->passiveFocusItem) {
            // Set focus on the last focus item
            setFocusItem(d->passiveFocusItem, focusEvent->reason());
        }
        break;
    }
}

/*!
    This event handler, for event \a focusEvent, can be reimplemented in a
    subclass to receive focus out events.

    The default implementation removes focus from any focus item, then removes
    focus from the scene.

    \sa QGraphicsItem::focusInEvent()
*/
void QGraphicsScene::focusOutEvent(QFocusEvent *focusEvent)
{
    Q_D(QGraphicsScene);
    d->hasFocus = false;
    d->passiveFocusItem = d->focusItem;
    setFocusItem(0, focusEvent->reason());

    // Remove all popups when the scene loses focus.
    if (!d->popupWidgets.isEmpty())
        d->removePopup(d->popupWidgets.first());
}

/*!
    This event handler, for event \a helpEvent, can be
    reimplemented in a subclass to receive help events. The events
    are of type QEvent::ToolTip, which are created when a tooltip is
    requested.

    The default implementation shows the tooltip of the topmost
    item, i.e., the item with the highest z-value, at the mouse
    cursor position. If no item has a tooltip set, this function
    does nothing.

   \sa QGraphicsItem::toolTip(), QGraphicsSceneHelpEvent
*/
void QGraphicsScene::helpEvent(QGraphicsSceneHelpEvent *helpEvent)
{
#ifdef QT_NO_TOOLTIP
    Q_UNUSED(helpEvent);
#else
    // Find the first item that does tooltips
    Q_D(QGraphicsScene);
    QList<QGraphicsItem *> itemsAtPos = d->itemsAtPosition(helpEvent->screenPos(),
                                                           helpEvent->scenePos(),
                                                           helpEvent->widget());
    QGraphicsItem *toolTipItem = 0;
    for (int i = 0; i < itemsAtPos.size(); ++i) {
        QGraphicsItem *tmp = itemsAtPos.at(i);
        if (tmp->d_func()->isProxyWidget()) {
            // if the item is a proxy widget, the event is forwarded to it
            sendEvent(tmp, helpEvent);
            if (helpEvent->isAccepted())
                return;
        }
        if (!tmp->toolTip().isEmpty()) {
            toolTipItem = tmp;
            break;
        }
    }

    // Show or hide the tooltip
    QString text;
    QPoint point;
    if (toolTipItem && !toolTipItem->toolTip().isEmpty()) {
        text = toolTipItem->toolTip();
        point = helpEvent->screenPos();
    }
    QToolTip::showText(point, text, helpEvent->widget());
    helpEvent->setAccepted(!text.isEmpty());
#endif
}

bool QGraphicsScenePrivate::itemAcceptsHoverEvents_helper(const QGraphicsItem *item) const
{
    return (item->d_ptr->acceptsHover
            || (item->d_ptr->isWidget
                && static_cast<const QGraphicsWidget *>(item)->d_func()->hasDecoration()))
           && !item->isBlockedByModalPanel();
}

/*!
    This event handler, for event \a hoverEvent, can be reimplemented in a
    subclass to receive hover enter events. The default implementation
    forwards the event to the topmost item that accepts hover events at the
    scene position from the event.

    \sa QGraphicsItem::hoverEvent(), QGraphicsItem::setAcceptHoverEvents()
*/
bool QGraphicsScenePrivate::dispatchHoverEvent(QGraphicsSceneHoverEvent *hoverEvent)
{
    if (allItemsIgnoreHoverEvents)
        return false;

    // Find the first item that accepts hover events, reusing earlier
    // calculated data is possible.
    if (cachedItemsUnderMouse.isEmpty()) {
        cachedItemsUnderMouse = itemsAtPosition(hoverEvent->screenPos(),
                                                hoverEvent->scenePos(),
                                                hoverEvent->widget());
    }

    QGraphicsItem *item = 0;
    for (int i = 0; i < cachedItemsUnderMouse.size(); ++i) {
        QGraphicsItem *tmp = cachedItemsUnderMouse.at(i);
        if (itemAcceptsHoverEvents_helper(tmp)) {
            item = tmp;
            break;
        }
    }

    // Find the common ancestor item for the new topmost hoverItem and the
    // last item in the hoverItem list.
    QGraphicsItem *commonAncestorItem = (item && !hoverItems.isEmpty()) ? item->commonAncestorItem(hoverItems.last()) : 0;
    while (commonAncestorItem && !itemAcceptsHoverEvents_helper(commonAncestorItem))
        commonAncestorItem = commonAncestorItem->parentItem();
    if (commonAncestorItem && commonAncestorItem->panel() != item->panel()) {
        // The common ancestor isn't in the same panel as the two hovered
        // items.
        commonAncestorItem = 0;
    }

    // Check if the common ancestor item is known.
    int index = commonAncestorItem ? hoverItems.indexOf(commonAncestorItem) : -1;
    // Send hover leaves to any existing hovered children of the common
    // ancestor item.
    for (int i = hoverItems.size() - 1; i > index; --i) {
        QGraphicsItem *lastItem = hoverItems.takeLast();
        if (itemAcceptsHoverEvents_helper(lastItem))
            sendHoverEvent(QEvent::GraphicsSceneHoverLeave, lastItem, hoverEvent);
    }

    // Item is a child of a known item. Generate enter events for the
    // missing links.
    QList<QGraphicsItem *> parents;
    QGraphicsItem *parent = item;
    while (parent && parent != commonAncestorItem) {
        parents.prepend(parent);
        if (parent->isPanel()) {
            // Stop at the panel - we don't deliver beyond this point.
            break;
        }
        parent = parent->parentItem();
    }
    for (int i = 0; i < parents.size(); ++i) {
        parent = parents.at(i);
        hoverItems << parent;
        if (itemAcceptsHoverEvents_helper(parent))
            sendHoverEvent(QEvent::GraphicsSceneHoverEnter, parent, hoverEvent);
    }

    // Generate a move event for the item itself
    if (item
        && !hoverItems.isEmpty()
        && item == hoverItems.last()) {
        sendHoverEvent(QEvent::GraphicsSceneHoverMove, item, hoverEvent);
        return true;
    }
    return false;
}

/*!
    \internal

    Handles all actions necessary to clean up the scene when the mouse leaves
    the view.
*/
void QGraphicsScenePrivate::leaveScene(QWidget *viewport)
{
#ifndef QT_NO_TOOLTIP
    QToolTip::hideText();
#endif
    QGraphicsView *view = qobject_cast<QGraphicsView *>(viewport->parent());
    // Send HoverLeave events to all existing hover items, topmost first.
    QGraphicsSceneHoverEvent hoverEvent;
    hoverEvent.setWidget(viewport);

    if (view) {
        QPoint cursorPos = QCursor::pos();
        hoverEvent.setScenePos(view->mapToScene(viewport->mapFromGlobal(cursorPos)));
        hoverEvent.setLastScenePos(hoverEvent.scenePos());
        hoverEvent.setScreenPos(cursorPos);
        hoverEvent.setLastScreenPos(hoverEvent.screenPos());
    }

    while (!hoverItems.isEmpty()) {
        QGraphicsItem *lastItem = hoverItems.takeLast();
        if (itemAcceptsHoverEvents_helper(lastItem))
            sendHoverEvent(QEvent::GraphicsSceneHoverLeave, lastItem, &hoverEvent);
    }
}

/*!
    This event handler, for event \a keyEvent, can be reimplemented in a
    subclass to receive keypress events. The default implementation forwards
    the event to current focus item.

    \sa QGraphicsItem::keyPressEvent(), focusItem()
*/
void QGraphicsScene::keyPressEvent(QKeyEvent *keyEvent)
{
    // ### Merge this function with keyReleaseEvent; they are identical
    // ### (except this comment).
    Q_D(QGraphicsScene);
    QGraphicsItem *item = !d->keyboardGrabberItems.isEmpty() ? d->keyboardGrabberItems.last() : 0;
    if (!item)
        item = focusItem();
    if (item) {
        QGraphicsItem *p = item;
        do {
            // Accept the event by default
            keyEvent->accept();
            // Send it; QGraphicsItem::keyPressEvent ignores it.  If the event
            // is filtered out, stop propagating it.
            if (p->isBlockedByModalPanel())
                break;
            if (!d->sendEvent(p, keyEvent))
                break;
        } while (!keyEvent->isAccepted() && !p->isPanel() && (p = p->parentItem()));
    } else {
        keyEvent->ignore();
    }
}

/*!
    This event handler, for event \a keyEvent, can be reimplemented in a
    subclass to receive key release events. The default implementation
    forwards the event to current focus item.

    \sa QGraphicsItem::keyReleaseEvent(), focusItem()
*/
void QGraphicsScene::keyReleaseEvent(QKeyEvent *keyEvent)
{
    // ### Merge this function with keyPressEvent; they are identical (except
    // ### this comment).
    Q_D(QGraphicsScene);
    QGraphicsItem *item = !d->keyboardGrabberItems.isEmpty() ? d->keyboardGrabberItems.last() : 0;
    if (!item)
        item = focusItem();
    if (item) {
        QGraphicsItem *p = item;
        do {
            // Accept the event by default
            keyEvent->accept();
            // Send it; QGraphicsItem::keyPressEvent ignores it.  If the event
            // is filtered out, stop propagating it.
            if (p->isBlockedByModalPanel())
                break;
            if (!d->sendEvent(p, keyEvent))
                break;
        } while (!keyEvent->isAccepted() && !p->isPanel() && (p = p->parentItem()));
    } else {
        keyEvent->ignore();
    }
}

/*!
    This event handler, for event \a mouseEvent, can be reimplemented
    in a subclass to receive mouse press events for the scene.

    The default implementation depends on the state of the scene. If
    there is a mouse grabber item, then the event is sent to the mouse
    grabber. Otherwise, it is forwarded to the topmost item that
    accepts mouse events at the scene position from the event, and
    that item promptly becomes the mouse grabber item.

    If there is no item at the given position on the scene, the
    selection area is reset, any focus item loses its input focus, and
    the event is then ignored.

    \sa QGraphicsItem::mousePressEvent(),
    QGraphicsItem::setAcceptedMouseButtons()
*/
void QGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
    Q_D(QGraphicsScene);
    if (d->mouseGrabberItems.isEmpty()) {
        // Dispatch hover events
        QGraphicsSceneHoverEvent hover;
        _q_hoverFromMouseEvent(&hover, mouseEvent);
        d->dispatchHoverEvent(&hover);
    }

    d->mousePressEventHandler(mouseEvent);
}

/*!
    This event handler, for event \a mouseEvent, can be reimplemented
    in a subclass to receive mouse move events for the scene.

    The default implementation depends on the mouse grabber state. If there is
    a mouse grabber item, the event is sent to the mouse grabber.  If there
    are any items that accept hover events at the current position, the event
    is translated into a hover event and accepted; otherwise it's ignored.

    \sa QGraphicsItem::mousePressEvent(), QGraphicsItem::mouseReleaseEvent(),
    QGraphicsItem::mouseDoubleClickEvent(), QGraphicsItem::setAcceptedMouseButtons()
*/
void QGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
    Q_D(QGraphicsScene);
    if (d->mouseGrabberItems.isEmpty()) {
        if (mouseEvent->buttons())
            return;
        QGraphicsSceneHoverEvent hover;
        _q_hoverFromMouseEvent(&hover, mouseEvent);
        mouseEvent->setAccepted(d->dispatchHoverEvent(&hover));
        return;
    }

    // Forward the event to the mouse grabber
    d->sendMouseEvent(mouseEvent);
    mouseEvent->accept();
}

/*!
    This event handler, for event \a mouseEvent, can be reimplemented
    in a subclass to receive mouse release events for the scene.

    The default implementation depends on the mouse grabber state.  If
    there is no mouse grabber, the event is ignored.  Otherwise, if
    there is a mouse grabber item, the event is sent to the mouse
    grabber. If this mouse release represents the last pressed button
    on the mouse, the mouse grabber item then loses the mouse grab.

    \sa QGraphicsItem::mousePressEvent(), QGraphicsItem::mouseMoveEvent(),
    QGraphicsItem::mouseDoubleClickEvent(), QGraphicsItem::setAcceptedMouseButtons()
*/
void QGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
    Q_D(QGraphicsScene);
    if (d->mouseGrabberItems.isEmpty()) {
        mouseEvent->ignore();
        return;
    }

    // Forward the event to the mouse grabber
    d->sendMouseEvent(mouseEvent);
    mouseEvent->accept();

    // Reset the mouse grabber when the last mouse button has been released.
    if (!mouseEvent->buttons()) {
        if (!d->mouseGrabberItems.isEmpty()) {
            d->lastMouseGrabberItem = d->mouseGrabberItems.last();
            if (d->lastMouseGrabberItemHasImplicitMouseGrab)
                d->mouseGrabberItems.last()->ungrabMouse();
        } else {
            d->lastMouseGrabberItem = 0;
        }

        // Generate a hoverevent
        QGraphicsSceneHoverEvent hoverEvent;
        _q_hoverFromMouseEvent(&hoverEvent, mouseEvent);
        d->dispatchHoverEvent(&hoverEvent);
    }
}

/*!
    This event handler, for event \a mouseEvent, can be reimplemented
    in a subclass to receive mouse doubleclick events for the scene.

    If someone doubleclicks on the scene, the scene will first receive
    a mouse press event, followed by a release event (i.e., a click),
    then a doubleclick event, and finally a release event. If the
    doubleclick event is delivered to a different item than the one
    that received the first press and release, it will be delivered as
    a press event. However, tripleclick events are not delivered as
    doubleclick events in this case.

    The default implementation is similar to mousePressEvent().

    \sa QGraphicsItem::mousePressEvent(), QGraphicsItem::mouseMoveEvent(),
    QGraphicsItem::mouseReleaseEvent(), QGraphicsItem::setAcceptedMouseButtons()
*/
void QGraphicsScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
    Q_D(QGraphicsScene);
    d->mousePressEventHandler(mouseEvent);
}

/*!
    This event handler, for event \a wheelEvent, can be reimplemented in a
    subclass to receive mouse wheel events for the scene.

    By default, the event is delivered to the topmost visible item under the
    cursor. If ignored, the event propagates to the item beneath, and again
    until the event is accepted, or it reaches the scene. If no items accept
    the event, it is ignored.

    \sa QGraphicsItem::wheelEvent()
*/
void QGraphicsScene::wheelEvent(QGraphicsSceneWheelEvent *wheelEvent)
{
    Q_D(QGraphicsScene);
    QList<QGraphicsItem *> wheelCandidates = d->itemsAtPosition(wheelEvent->screenPos(),
                                                                wheelEvent->scenePos(),
                                                                wheelEvent->widget());

#ifdef Q_WS_MAC
    // On Mac, ignore the event if the first item under the mouse is not the last opened
    // popup (or one of its descendant)
    if (!d->popupWidgets.isEmpty() && !wheelCandidates.isEmpty() && wheelCandidates.first() != d->popupWidgets.back() && !d->popupWidgets.back()->isAncestorOf(wheelCandidates.first())) {
        wheelEvent->accept();
        return;
    }
#else
    // Find the first popup under the mouse (including the popup's descendants) starting from the last.
    // Remove all popups after the one found, or all or them if no popup is under the mouse.
    // Then continue with the event.
    QList<QGraphicsWidget *>::const_iterator iter = d->popupWidgets.end();
    while (--iter >= d->popupWidgets.begin() && !wheelCandidates.isEmpty()) {
        if (wheelCandidates.first() == *iter || (*iter)->isAncestorOf(wheelCandidates.first()))
            break;
        d->removePopup(*iter);
    }
#endif

    bool hasSetFocus = false;
    foreach (QGraphicsItem *item, wheelCandidates) {
        if (!hasSetFocus && item->isEnabled()
            && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) {
            if (item->isWidget() && static_cast<QGraphicsWidget *>(item)->focusPolicy() == Qt::WheelFocus) {
                hasSetFocus = true;
                if (item != focusItem())
                    setFocusItem(item, Qt::MouseFocusReason);
            }
        }

        wheelEvent->setPos(item->d_ptr->genericMapFromScene(wheelEvent->scenePos(),
                                                            wheelEvent->widget()));
        wheelEvent->accept();
        bool isPanel = item->isPanel();
        d->sendEvent(item, wheelEvent);
        if (isPanel || wheelEvent->isAccepted())
            break;
    }
}

/*!
    This event handler, for event \a event, can be reimplemented in a
    subclass to receive input method events for the scene.

    The default implementation forwards the event to the focusItem().
    If no item currently has focus or the current focus item does not
    accept input methods, this function does nothing.

    \sa QGraphicsItem::inputMethodEvent()
*/
void QGraphicsScene::inputMethodEvent(QInputMethodEvent *event)
{
    Q_D(QGraphicsScene);
    if (d->focusItem && (d->focusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod))
        d->sendEvent(d->focusItem, event);
}

/*!
    Draws the background of the scene using \a painter, before any items and
    the foreground are drawn. Reimplement this function to provide a custom
    background for the scene.

    All painting is done in \e scene coordinates. The \a rect
    parameter is the exposed rectangle.

    If all you want is to define a color, texture, or gradient for the
    background, you can call setBackgroundBrush() instead.

    \sa drawForeground(), drawItems()
*/
void QGraphicsScene::drawBackground(QPainter *painter, const QRectF &rect)
{
    Q_D(QGraphicsScene);

    if (d->backgroundBrush.style() != Qt::NoBrush) {
        if (d->painterStateProtection)
            painter->save();
        painter->setBrushOrigin(0, 0);
        painter->fillRect(rect, backgroundBrush());
        if (d->painterStateProtection)
            painter->restore();
    }
}

/*!
    Draws the foreground of the scene using \a painter, after the background
    and all items have been drawn. Reimplement this function to provide a
    custom foreground for the scene.

    All painting is done in \e scene coordinates. The \a rect
    parameter is the exposed rectangle.

    If all you want is to define a color, texture or gradient for the
    foreground, you can call setForegroundBrush() instead.

    \sa drawBackground(), drawItems()
*/
void QGraphicsScene::drawForeground(QPainter *painter, const QRectF &rect)
{
    Q_D(QGraphicsScene);

    if (d->foregroundBrush.style() != Qt::NoBrush) {
        if (d->painterStateProtection)
            painter->save();
        painter->setBrushOrigin(0, 0);
        painter->fillRect(rect, foregroundBrush());
        if (d->painterStateProtection)
            painter->restore();
    }
}

static void _q_paintItem(QGraphicsItem *item, QPainter *painter,
                         const QStyleOptionGraphicsItem *option, QWidget *widget,
                         bool useWindowOpacity, bool painterStateProtection)
{
    if (!item->isWidget()) {
        item->paint(painter, option, widget);
        return;
    }
    QGraphicsWidget *widgetItem = static_cast<QGraphicsWidget *>(item);
    QGraphicsProxyWidget *proxy = qobject_cast<QGraphicsProxyWidget *>(widgetItem);
    const qreal windowOpacity = (proxy && proxy->widget() && useWindowOpacity)
                                ? proxy->widget()->windowOpacity() : 1.0;
    const qreal oldPainterOpacity = painter->opacity();

    if (qFuzzyIsNull(windowOpacity))
        return;
    // Set new painter opacity.
    if (windowOpacity < 1.0)
        painter->setOpacity(oldPainterOpacity * windowOpacity);

    // set layoutdirection on the painter
    Qt::LayoutDirection oldLayoutDirection = painter->layoutDirection();
    painter->setLayoutDirection(widgetItem->layoutDirection());

    if (widgetItem->isWindow() && widgetItem->windowType() != Qt::Popup && widgetItem->windowType() != Qt::ToolTip
        && !(widgetItem->windowFlags() & Qt::FramelessWindowHint)) {
        if (painterStateProtection)
            painter->save();
        widgetItem->paintWindowFrame(painter, option, widget);
        if (painterStateProtection)
            painter->restore();
    } else if (widgetItem->autoFillBackground()) {
        painter->fillRect(option->exposedRect, widgetItem->palette().window());
    }

    widgetItem->paint(painter, option, widget);

    // Restore layoutdirection on the painter.
    painter->setLayoutDirection(oldLayoutDirection);
    // Restore painter opacity.
    if (windowOpacity < 1.0)
        painter->setOpacity(oldPainterOpacity);
}

static void _q_paintIntoCache(QPixmap *pix, QGraphicsItem *item, const QRegion &pixmapExposed,
                              const QTransform &itemToPixmap, QPainter::RenderHints renderHints,
                              const QStyleOptionGraphicsItem *option, bool painterStateProtection)
{
    QPixmap subPix;
    QPainter pixmapPainter;
    QRect br = pixmapExposed.boundingRect();

    // Don't use subpixmap if we get a full update.
    if (pixmapExposed.isEmpty() || (pixmapExposed.rectCount() == 1 && br.contains(pix->rect()))) {
        pix->fill(Qt::transparent);
        pixmapPainter.begin(pix);
    } else {
        subPix = QPixmap(br.size());
        subPix.fill(Qt::transparent);
        pixmapPainter.begin(&subPix);
        pixmapPainter.translate(-br.topLeft());
        if (!pixmapExposed.isEmpty()) {
            // Applied to subPix; paint is adjusted to the coordinate space is
            // correct.
            pixmapPainter.setClipRegion(pixmapExposed);
        }
    }

    pixmapPainter.setRenderHints(pixmapPainter.renderHints(), false);
    pixmapPainter.setRenderHints(renderHints, true);
    pixmapPainter.setWorldTransform(itemToPixmap, true);

    // Render.
    _q_paintItem(item, &pixmapPainter, option, 0, false, painterStateProtection);
    pixmapPainter.end();

    if (!subPix.isNull()) {
        // Blit the subpixmap into the main pixmap.
        pixmapPainter.begin(pix);
        pixmapPainter.setCompositionMode(QPainter::CompositionMode_Source);
        pixmapPainter.setClipRegion(pixmapExposed);
        pixmapPainter.drawPixmap(br.topLeft(), subPix);
        pixmapPainter.end();
    }
}

// Copied from qpaintengine_vg.cpp
// Returns true for 90, 180, and 270 degree rotations.
static inline bool transformIsSimple(const QTransform& transform)
{
    QTransform::TransformationType type = transform.type();
    if (type <= QTransform::TxScale) {
        return true;
    } else if (type == QTransform::TxRotate) {
        // Check for 90, and 270 degree rotations.
        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 == -1.0f && m21 == -1.0f)
                return true; // 90 degrees inverted y.
            else if (m12 == 1.0f && m21 == 1.0f)
                return true; // 270 degrees inverted y.
        }
    }
    return false;
}

/*!
    \internal

    Draws items directly, or using cache.
*/
void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painter,
                                           const QStyleOptionGraphicsItem *option, QWidget *widget,
                                           bool painterStateProtection)
{
    QGraphicsItemPrivate *itemd = item->d_ptr.data();
    QGraphicsItem::CacheMode cacheMode = QGraphicsItem::CacheMode(itemd->cacheMode);

    // Render directly, using no cache.
    if (cacheMode == QGraphicsItem::NoCache
#ifdef Q_WS_X11
        || !X11->use_xrender
#endif
        ) {
        _q_paintItem(static_cast<QGraphicsWidget *>(item), painter, option, widget, true, painterStateProtection);
        return;
    }

    const qreal oldPainterOpacity = painter->opacity();
    qreal newPainterOpacity = oldPainterOpacity;
    QGraphicsProxyWidget *proxy = item->isWidget() ? qobject_cast<QGraphicsProxyWidget *>(static_cast<QGraphicsWidget *>(item)) : 0;
    if (proxy && proxy->widget()) {
        const qreal windowOpacity = proxy->widget()->windowOpacity();
        if (windowOpacity < 1.0)
            newPainterOpacity *= windowOpacity;
    }

    // Item's (local) bounding rect
    QRectF brect = item->boundingRect();
    QRectF adjustedBrect(brect);
    _q_adjustRect(&adjustedBrect);
    if (adjustedBrect.isEmpty())
        return;

    // Fetch the off-screen transparent buffer and exposed area info.
    QPixmapCache::Key pixmapKey;
    QPixmap pix;
    bool pixmapFound;
    QGraphicsItemCache *itemCache = itemd->extraItemCache();
    if (cacheMode == QGraphicsItem::ItemCoordinateCache) {
        pixmapKey = itemCache->key;
    } else {
        pixmapKey = itemCache->deviceData.value(widget).key;
    }

    // Find pixmap in cache.
    pixmapFound = QPixmapCache::find(pixmapKey, &pix);

    // Render using item coordinate cache mode.
    if (cacheMode == QGraphicsItem::ItemCoordinateCache) {
        QSize pixmapSize;
        bool fixedCacheSize = false;
        QRect br = brect.toAlignedRect();
        if ((fixedCacheSize = itemCache->fixedSize.isValid())) {
            pixmapSize = itemCache->fixedSize;
        } else {
            pixmapSize = br.size();
        }

        // Create or recreate the pixmap.
        int adjust = itemCache->fixedSize.isValid() ? 0 : 2;
        QSize adjustSize(adjust*2, adjust*2);
        br.adjust(-adjust, -adjust, adjust, adjust);
        if (pix.isNull() || (!fixedCacheSize && (pixmapSize + adjustSize) != pix.size())) {
            pix = QPixmap(pixmapSize + adjustSize);
            itemCache->boundingRect = br;
            itemCache->exposed.clear();
            itemCache->allExposed = true;
        } else if (itemCache->boundingRect != br) {
            itemCache->boundingRect = br;
            itemCache->exposed.clear();
            itemCache->allExposed = true;
        }

        // Redraw any newly exposed areas.
        if (itemCache->allExposed || !itemCache->exposed.isEmpty()) {

            //We know that we will modify the pixmap, removing it from the cache
            //will detach the one we have and avoid a deep copy
            if (pixmapFound)
                QPixmapCache::remove(pixmapKey);

            // Fit the item's bounding rect into the pixmap's coordinates.
            QTransform itemToPixmap;
            if (fixedCacheSize) {
                const QPointF scale(pixmapSize.width() / brect.width(), pixmapSize.height() / brect.height());
                itemToPixmap.scale(scale.x(), scale.y());
            }
            itemToPixmap.translate(-br.x(), -br.y());

            // Generate the item's exposedRect and map its list of expose
            // rects to device coordinates.
            styleOptionTmp = *option;
            QRegion pixmapExposed;
            QRectF exposedRect;
            if (!itemCache->allExposed) {
                for (int i = 0; i < itemCache->exposed.size(); ++i) {
                    QRectF r = itemCache->exposed.at(i);
                    exposedRect |= r;
                    pixmapExposed += itemToPixmap.mapRect(r).toAlignedRect();
                }
            } else {
                exposedRect = brect;
            }
            styleOptionTmp.exposedRect = exposedRect;

            // Render.
            _q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(),
                              &styleOptionTmp, painterStateProtection);

            // insert this pixmap into the cache.
            itemCache->key = QPixmapCache::insert(pix);

            // Reset expose data.
            itemCache->allExposed = false;
            itemCache->exposed.clear();
        }

        // Redraw the exposed area using the transformed painter. Depending on
        // the hardware, this may be a server-side operation, or an expensive
        // qpixmap-image-transform-pixmap roundtrip.
        if (newPainterOpacity != oldPainterOpacity) {
            painter->setOpacity(newPainterOpacity);
            painter->drawPixmap(br.topLeft(), pix);
            painter->setOpacity(oldPainterOpacity);
        } else {
            painter->drawPixmap(br.topLeft(), pix);
        }
        return;
    }

    // Render using device coordinate cache mode.
    if (cacheMode == QGraphicsItem::DeviceCoordinateCache) {
        // Find the item's bounds in device coordinates.
        QRectF deviceBounds = painter->worldTransform().mapRect(brect);
        QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
        if (deviceRect.isEmpty())
            return;
        QRect viewRect = widget ? widget->rect() : QRect();
        if (widget && !viewRect.intersects(deviceRect))
            return;

        // Resort to direct rendering if the device rect exceeds the
        // (optional) maximum bounds. (QGraphicsSvgItem uses this).
        QSize maximumCacheSize =
            itemd->extra(QGraphicsItemPrivate::ExtraMaxDeviceCoordCacheSize).toSize();
        if (!maximumCacheSize.isEmpty()
            && (deviceRect.width() > maximumCacheSize.width()
                || deviceRect.height() > maximumCacheSize.height())) {
            _q_paintItem(static_cast<QGraphicsWidget *>(item), painter, option, widget,
                         oldPainterOpacity != newPainterOpacity, painterStateProtection);
            return;
        }

        // Create or reuse offscreen pixmap, possibly scroll/blit from the old one.
        // If the world transform is rotated we always recreate the cache to avoid
        // wrong blending.
        bool pixModified = false;
        QGraphicsItemCache::DeviceData *deviceData = &itemCache->deviceData[widget];
        bool invertable = true;
        QTransform diff = deviceData->lastTransform.inverted(&invertable);
        if (invertable)
            diff *= painter->worldTransform();
        deviceData->lastTransform = painter->worldTransform();
        bool allowPartialCacheExposure = false;
        bool simpleTransform = invertable && diff.type() <= QTransform::TxTranslate
                               && transformIsSimple(painter->worldTransform());
        if (!simpleTransform) {
            pixModified = true;
            itemCache->allExposed = true;
            itemCache->exposed.clear();
            deviceData->cacheIndent = QPoint();
            pix = QPixmap();
        } else if (!viewRect.isNull()) {
            allowPartialCacheExposure = deviceData->cacheIndent != QPoint();
        }

        // Allow partial cache exposure if the device rect isn't fully contained and
        // deviceRect is 20% taller or wider than the viewRect.
        if (!allowPartialCacheExposure && !viewRect.isNull() && !viewRect.contains(deviceRect)) {
            allowPartialCacheExposure = (viewRect.width() * 1.2 < deviceRect.width())
                                         || (viewRect.height() * 1.2 < deviceRect.height());
        }

        QRegion scrollExposure;
        if (allowPartialCacheExposure) {
            // Part of pixmap is drawn. Either device contains viewrect (big
            // item covers whole screen) or parts of device are outside the
            // viewport. In either case the device rect must be the intersect
            // between the two.
            int dx = deviceRect.left() < viewRect.left() ? viewRect.left() - deviceRect.left() : 0;
            int dy = deviceRect.top() < viewRect.top() ? viewRect.top() - deviceRect.top() : 0;
            QPoint newCacheIndent(dx, dy);
            deviceRect &= viewRect;

            if (pix.isNull()) {
                deviceData->cacheIndent = QPoint();
                itemCache->allExposed = true;
                itemCache->exposed.clear();
                pixModified = true;
            }

            // Copy / "scroll" the old pixmap onto the new ole and calculate
            // scrolled exposure.
            if (newCacheIndent != deviceData->cacheIndent || deviceRect.size() != pix.size()) {
                QPoint diff = newCacheIndent - deviceData->cacheIndent;
                QPixmap newPix(deviceRect.size());
                // ### Investigate removing this fill (test with Plasma and
                // graphicssystem raster).
                newPix.fill(Qt::transparent);
                if (!pix.isNull()) {
                    QPainter newPixPainter(&newPix);
                    newPixPainter.drawPixmap(-diff, pix);
                    newPixPainter.end();
                }
                QRegion exposed;
                exposed += newPix.rect();
                if (!pix.isNull())
                    exposed -= QRect(-diff, pix.size());
                scrollExposure = exposed;

                pix = newPix;
                pixModified = true;
            }
            deviceData->cacheIndent = newCacheIndent;
        } else {
            // Full pixmap is drawn.
            deviceData->cacheIndent = QPoint();

            // Auto-adjust the pixmap size.
            if (deviceRect.size() != pix.size()) {
                // exposed needs to cover the whole pixmap
                pix = QPixmap(deviceRect.size());
                pixModified = true;
                itemCache->allExposed = true;
                itemCache->exposed.clear();
            }
        }

        // Check for newly invalidated areas.
        if (itemCache->allExposed || !itemCache->exposed.isEmpty() || !scrollExposure.isEmpty()) {
            //We know that we will modify the pixmap, removing it from the cache
            //will detach the one we have and avoid a deep copy
            if (pixmapFound)
                QPixmapCache::remove(pixmapKey);

            // Construct an item-to-pixmap transform.
            QPointF p = deviceRect.topLeft();
            QTransform itemToPixmap = painter->worldTransform();
            if (!p.isNull())
                itemToPixmap *= QTransform::fromTranslate(-p.x(), -p.y());

            // Map the item's logical expose to pixmap coordinates.
            QRegion pixmapExposed = scrollExposure;
            if (!itemCache->allExposed) {
                const QVector<QRectF> &exposed = itemCache->exposed;
                for (int i = 0; i < exposed.size(); ++i)
                    pixmapExposed += itemToPixmap.mapRect(exposed.at(i)).toRect().adjusted(-1, -1, 1, 1);
            }

            // Calculate the style option's exposedRect.
            QRectF br;
            if (itemCache->allExposed) {
                br = item->boundingRect();
            } else {
                const QVector<QRectF> &exposed = itemCache->exposed;
                for (int i = 0; i < exposed.size(); ++i)
                    br |= exposed.at(i);
                QTransform pixmapToItem = itemToPixmap.inverted();
                foreach (QRect r, scrollExposure.rects())
                    br |= pixmapToItem.mapRect(r);
            }
            styleOptionTmp = *option;
            styleOptionTmp.exposedRect = br.adjusted(-1, -1, 1, 1);

            // Render the exposed areas.
            _q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(),
                              &styleOptionTmp, painterStateProtection);

            // Reset expose data.
            pixModified = true;
            itemCache->allExposed = false;
            itemCache->exposed.clear();
        }

        if (pixModified) {
            // Insert this pixmap into the cache.
            deviceData->key = QPixmapCache::insert(pix);
        }

        // Redraw the exposed area using an untransformed painter. This
        // effectively becomes a bitblit that does not transform the cache.
        QTransform restoreTransform = painter->worldTransform();
        painter->setWorldTransform(QTransform());
        if (newPainterOpacity != oldPainterOpacity) {
            painter->setOpacity(newPainterOpacity);
            painter->drawPixmap(deviceRect.topLeft(), pix);
            painter->setOpacity(oldPainterOpacity);
        } else {
            painter->drawPixmap(deviceRect.topLeft(), pix);
        }
        painter->setWorldTransform(restoreTransform);
        return;
    }
}

void QGraphicsScenePrivate::drawItems(QPainter *painter, const QTransform *const viewTransform,
                                      QRegion *exposedRegion, QWidget *widget)
{
    // Make sure we don't have unpolished items before we draw.
    if (!unpolishedItems.isEmpty())
        _q_polishItems();

    updateAll = false;
    QRectF exposedSceneRect;
    if (exposedRegion && indexMethod != QGraphicsScene::NoIndex) {
        exposedSceneRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1);
        if (viewTransform)
            exposedSceneRect = viewTransform->inverted().mapRect(exposedSceneRect);
    }
    const QList<QGraphicsItem *> tli = index->estimateTopLevelItems(exposedSceneRect, Qt::AscendingOrder);
    for (int i = 0; i < tli.size(); ++i)
        drawSubtreeRecursive(tli.at(i), painter, viewTransform, exposedRegion, widget);
}

void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter,
                                                 const QTransform *const viewTransform,
                                                 QRegion *exposedRegion, QWidget *widget,
                                                 qreal parentOpacity, const QTransform *const effectTransform)
{
    Q_ASSERT(item);

    if (!item->d_ptr->visible)
        return;

    const bool itemHasContents = !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents);
    const bool itemHasChildren = !item->d_ptr->children.isEmpty();
    if (!itemHasContents && !itemHasChildren)
        return; // Item has neither contents nor children!(?)

    const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
    const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
    if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
        return;

    QTransform transform(Qt::Uninitialized);
    QTransform *transformPtr = 0;
    bool translateOnlyTransform = false;
#define ENSURE_TRANSFORM_PTR \
    if (!transformPtr) { \
        Q_ASSERT(!itemIsUntransformable); \
        if (viewTransform) { \
            transform = item->d_ptr->sceneTransform; \
            transform *= *viewTransform; \
            transformPtr = &transform; \
        } else { \
            transformPtr = &item->d_ptr->sceneTransform; \
            translateOnlyTransform = item->d_ptr->sceneTransformTranslateOnly; \
        } \
    }

    // Update the item's scene transform if the item is transformable;
    // otherwise calculate the full transform,
    bool wasDirtyParentSceneTransform = false;
    const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable();
    if (itemIsUntransformable) {
        transform = item->deviceTransform(viewTransform ? *viewTransform : QTransform());
        transformPtr = &transform;
    } else if (item->d_ptr->dirtySceneTransform) {
        item->d_ptr->updateSceneTransformFromParent();
        Q_ASSERT(!item->d_ptr->dirtySceneTransform);
        wasDirtyParentSceneTransform = true;
    }

    const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
    bool drawItem = itemHasContents && !itemIsFullyTransparent;
    if (drawItem) {
        const QRectF brect = adjustedItemEffectiveBoundingRect(item);
        ENSURE_TRANSFORM_PTR
        QRect viewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy()).toAlignedRect()
                                                        : transformPtr->mapRect(brect).toAlignedRect();
        viewBoundingRect.adjust(-int(rectAdjust), -int(rectAdjust), rectAdjust, rectAdjust);
        if (widget)
            item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
        drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect)
                                 : !viewBoundingRect.normalized().isEmpty();
        if (!drawItem) {
            if (!itemHasChildren)
                return;
            if (itemClipsChildrenToShape) {
                if (wasDirtyParentSceneTransform)
                    item->d_ptr->invalidateChildrenSceneTransform();
                return;
            }
        }
    } // else we know for sure this item has children we must process.

    if (itemHasChildren && itemClipsChildrenToShape)
        ENSURE_TRANSFORM_PTR;

#ifndef QT_NO_GRAPHICSEFFECT
    if (item->d_ptr->graphicsEffect && item->d_ptr->graphicsEffect->isEnabled()) {
        ENSURE_TRANSFORM_PTR;
        QGraphicsItemPaintInfo info(viewTransform, transformPtr, effectTransform, exposedRegion, widget, &styleOptionTmp,
                                    painter, opacity, wasDirtyParentSceneTransform, itemHasContents && !itemIsFullyTransparent);
        QGraphicsEffectSource *source = item->d_ptr->graphicsEffect->d_func()->source;
        QGraphicsItemEffectSourcePrivate *sourced = static_cast<QGraphicsItemEffectSourcePrivate *>
                                                    (source->d_func());
        sourced->info = &info;
        const QTransform restoreTransform = painter->worldTransform();
        if (effectTransform)
            painter->setWorldTransform(*transformPtr * *effectTransform);
        else
            painter->setWorldTransform(*transformPtr);
        painter->setOpacity(opacity);

        if (sourced->currentCachedSystem() != Qt::LogicalCoordinates
            && sourced->lastEffectTransform != painter->worldTransform())
        {
            if (sourced->lastEffectTransform.type() <= QTransform::TxTranslate
                && painter->worldTransform().type() <= QTransform::TxTranslate)
            {
                QRectF sourceRect = sourced->boundingRect(Qt::DeviceCoordinates);
                QRect effectRect = sourced->paddedEffectRect(Qt::DeviceCoordinates, sourced->currentCachedMode(), sourceRect);

                sourced->setCachedOffset(effectRect.topLeft());
            } else {
                sourced->invalidateCache(QGraphicsEffectSourcePrivate::TransformChanged);
            }

            sourced->lastEffectTransform = painter->worldTransform();
        }

        item->d_ptr->graphicsEffect->draw(painter);
        painter->setWorldTransform(restoreTransform);
        sourced->info = 0;
    } else
#endif //QT_NO_GRAPHICSEFFECT
    {
        draw(item, painter, viewTransform, transformPtr, exposedRegion, widget, opacity,
             effectTransform, wasDirtyParentSceneTransform, drawItem);
    }
}

static inline void setClip(QPainter *painter, QGraphicsItem *item)
{
    painter->save();
    QRectF clipRect;
    const QPainterPath clipPath(item->shape());
    if (QPathClipper::pathToRect(clipPath, &clipRect))
        painter->setClipRect(clipRect, Qt::IntersectClip);
    else
        painter->setClipPath(clipPath, Qt::IntersectClip);
}

static inline void setWorldTransform(QPainter *painter, const QTransform *const transformPtr,
                                     const QTransform *effectTransform)
{
    Q_ASSERT(transformPtr);
    if (effectTransform)
        painter->setWorldTransform(*transformPtr * *effectTransform);
    else
        painter->setWorldTransform(*transformPtr);
}

void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const QTransform *const viewTransform,
                                 const QTransform *const transformPtr, QRegion *exposedRegion, QWidget *widget,
                                 qreal opacity, const QTransform *effectTransform,
                                 bool wasDirtyParentSceneTransform, bool drawItem)
{
    const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
    const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
    const bool itemHasChildren = !item->d_ptr->children.isEmpty();
    bool setChildClip = itemClipsChildrenToShape;
    bool itemHasChildrenStackedBehind = false;

    int i = 0;
    if (itemHasChildren) {
        if (itemClipsChildrenToShape)
            setWorldTransform(painter, transformPtr, effectTransform);

        item->d_ptr->ensureSortedChildren();
        // Items with the 'ItemStacksBehindParent' flag are put in front of the list
        // so all we have to do is to check the first item.
        itemHasChildrenStackedBehind = (item->d_ptr->children.at(0)->d_ptr->flags
                                        & QGraphicsItem::ItemStacksBehindParent);

        if (itemHasChildrenStackedBehind) {
            if (itemClipsChildrenToShape) {
                setClip(painter, item);
                setChildClip = false;
            }

            // Draw children behind
            for (i = 0; i < item->d_ptr->children.size(); ++i) {
                QGraphicsItem *child = item->d_ptr->children.at(i);
                if (wasDirtyParentSceneTransform)
                    child->d_ptr->dirtySceneTransform = 1;
                if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent))
                    break;
                if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
                    continue;
                drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform);
            }
        }
    }

    // Draw item
    if (drawItem) {
        Q_ASSERT(!itemIsFullyTransparent);
        Q_ASSERT(!(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents));
        Q_ASSERT(transformPtr);
        item->d_ptr->initStyleOption(&styleOptionTmp, *transformPtr, exposedRegion
                                     ? *exposedRegion : QRegion(), exposedRegion == 0);

        const bool itemClipsToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsToShape;
        bool restorePainterClip = false;

        if (!itemHasChildren || !itemClipsChildrenToShape) {
            // Item does not have children or clip children to shape.
            setWorldTransform(painter, transformPtr, effectTransform);
            if ((restorePainterClip = itemClipsToShape))
                setClip(painter, item);
        } else if (itemHasChildrenStackedBehind){
            // Item clips children to shape and has children stacked behind, which means
            // the painter is already clipped to the item's shape.
            if (itemClipsToShape) {
                // The clip is already correct. Ensure correct world transform.
                setWorldTransform(painter, transformPtr, effectTransform);
            } else {
                // Remove clip (this also ensures correct world transform).
                painter->restore();
                setChildClip = true;
            }
        } else if (itemClipsToShape) {
            // Item clips children and itself to shape. It does not have hildren stacked
            // behind, which means the clip has not yet been set. We set it now and re-use it
            // for the children.
            setClip(painter, item);
            setChildClip = false;
        }

        if (painterStateProtection && !restorePainterClip)
            painter->save();

        painter->setOpacity(opacity);
        if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget)
            item->paint(painter, &styleOptionTmp, widget);
        else
            drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection);

        if (painterStateProtection || restorePainterClip)
            painter->restore();

        static int drawRect = qgetenv("QT_DRAW_SCENE_ITEM_RECTS").toInt();
        if (drawRect) {
            QPen oldPen = painter->pen();
            QBrush oldBrush = painter->brush();
            quintptr ptr = reinterpret_cast<quintptr>(item);
            const QColor color = QColor::fromHsv(ptr % 255, 255, 255);
            painter->setPen(color);
            painter->setBrush(Qt::NoBrush);
            painter->drawRect(adjustedItemBoundingRect(item));
            painter->setPen(oldPen);
            painter->setBrush(oldBrush);
        }
    }

    // Draw children in front
    if (itemHasChildren) {
        if (setChildClip)
            setClip(painter, item);

        for (; i < item->d_ptr->children.size(); ++i) {
            QGraphicsItem *child = item->d_ptr->children.at(i);
            if (wasDirtyParentSceneTransform)
                child->d_ptr->dirtySceneTransform = 1;
            if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
                continue;
            drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform);
        }

        // Restore child clip
        if (itemClipsChildrenToShape)
            painter->restore();
    }
}

void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, bool invalidateChildren,
                                      bool force, bool ignoreOpacity, bool removingItemFromScene,
                                      bool updateBoundingRect)
{
    Q_ASSERT(item);
    if (updateAll)
        return;

    if (removingItemFromScene && !ignoreOpacity && !item->d_ptr->ignoreOpacity) {
        // If any of the item's ancestors ignore opacity, it means that the opacity
        // was set to 0 (and the update request has not yet been processed). That
        // also means that we have to ignore the opacity for the item itself; otherwise
        // things like: parent->setOpacity(0); scene->removeItem(child) won't work.
        // Note that we only do this when removing items from the scene. In all other
        // cases the ignoreOpacity bit propagates properly in processDirtyItems, but
        // since the item is removed immediately it won't be processed there.
        QGraphicsItem *p = item->d_ptr->parent;
        while (p) {
            if (p->d_ptr->ignoreOpacity) {
                item->d_ptr->ignoreOpacity = true;
                break;
            }
            p = p->d_ptr->parent;
        }
    }

    if (item->d_ptr->discardUpdateRequest(/*ignoreVisibleBit=*/force,
                                          /*ignoreDirtyBit=*/removingItemFromScene || invalidateChildren,
                                          /*ignoreOpacity=*/ignoreOpacity)) {
        if (item->d_ptr->dirty) {
            // The item is already marked as dirty and will be processed later. However,
            // we have to make sure ignoreVisible and ignoreOpacity are set properly;
            // otherwise things like: item->update(); item->hide() (force is now true)
            // won't work as expected.
            if (force)
                item->d_ptr->ignoreVisible = 1;
            if (ignoreOpacity)
                item->d_ptr->ignoreOpacity = 1;
        }
        return;
    }

    const bool fullItemUpdate = rect.isNull();
    if (!fullItemUpdate && rect.isEmpty())
        return;

    if (!processDirtyItemsEmitted) {
        QMetaMethod method = q_ptr->metaObject()->method(processDirtyItemsIndex);
        method.invoke(q_ptr, Qt::QueuedConnection);
//        QMetaObject::invokeMethod(q_ptr, "_q_processDirtyItems", Qt::QueuedConnection);
        processDirtyItemsEmitted = true;
    }

    if (removingItemFromScene) {
        // Note that this function can be called from the item's destructor, so
        // do NOT call any virtual functions on it within this block.
        if (isSignalConnected(changedSignalIndex) || views.isEmpty()) {
            // This block of code is kept for compatibility. Since 4.5, by default
            // QGraphicsView does not connect the signal and we use the below
            // method of delivering updates.
            q_func()->update();
            return;
        }

        for (int i = 0; i < views.size(); ++i) {
            QGraphicsViewPrivate *viewPrivate = views.at(i)->d_func();
            QRect rect = item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport);
            rect.translate(viewPrivate->dirtyScrollOffset);
            viewPrivate->updateRect(rect);
        }
        return;
    }

    bool hasNoContents = item->d_ptr->flags & QGraphicsItem::ItemHasNoContents;
    if (!hasNoContents) {
        item->d_ptr->dirty = 1;
        if (fullItemUpdate)
            item->d_ptr->fullUpdatePending = 1;
        else if (!item->d_ptr->fullUpdatePending)
            item->d_ptr->needsRepaint |= rect;
    } else if (item->d_ptr->graphicsEffect) {
        invalidateChildren = true;
    }

    if (invalidateChildren) {
        item->d_ptr->allChildrenDirty = 1;
        item->d_ptr->dirtyChildren = 1;
    }

    if (force)
        item->d_ptr->ignoreVisible = 1;
    if (ignoreOpacity)
        item->d_ptr->ignoreOpacity = 1;

    if (!updateBoundingRect)
        item->d_ptr->markParentDirty();
}

static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item,
                                const QRectF &rect, bool itemIsUntransformable)
{
    Q_ASSERT(view);
    Q_ASSERT(item);

    QGraphicsItem *itemq = static_cast<QGraphicsItem *>(item->q_ptr);
    QGraphicsView *viewq = static_cast<QGraphicsView *>(view->q_ptr);

    if (itemIsUntransformable) {
        const QTransform xform = itemq->deviceTransform(viewq->viewportTransform());
        if (!item->hasBoundingRegionGranularity)
            return view->updateRectF(xform.mapRect(rect));
        return view->updateRegion(rect, xform);
    }

    if (item->sceneTransformTranslateOnly && view->identityMatrix) {
        const qreal dx = item->sceneTransform.dx();
        const qreal dy = item->sceneTransform.dy();
        QRectF r(rect);
        r.translate(dx - view->horizontalScroll(), dy - view->verticalScroll());
        return view->updateRectF(r);
    }

    if (!viewq->isTransformed()) {
        if (!item->hasBoundingRegionGranularity)
            return view->updateRectF(item->sceneTransform.mapRect(rect));
        return view->updateRegion(rect, item->sceneTransform);
    }

    QTransform xform = item->sceneTransform;
    xform *= viewq->viewportTransform();
    if (!item->hasBoundingRegionGranularity)
        return view->updateRectF(xform.mapRect(rect));
    return view->updateRegion(rect, xform);
}

void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren,
                                                       qreal parentOpacity)
{
    Q_Q(QGraphicsScene);
    Q_ASSERT(item);
    Q_ASSERT(!updateAll);

    if (!item->d_ptr->dirty && !item->d_ptr->dirtyChildren) {
        resetDirtyItem(item);
        return;
    }

    const bool itemIsHidden = !item->d_ptr->ignoreVisible && !item->d_ptr->visible;
    if (itemIsHidden) {
        resetDirtyItem(item, /*recursive=*/true);
        return;
    }

    bool itemHasContents = !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents);
    const bool itemHasChildren = !item->d_ptr->children.isEmpty();
    if (!itemHasContents) {
        if (!itemHasChildren) {
            resetDirtyItem(item);
            return; // Item has neither contents nor children!(?)
        }
        if (item->d_ptr->graphicsEffect)
            itemHasContents = true;
    }

    const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
    const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity
                                        && QGraphicsItemPrivate::isOpacityNull(opacity);
    if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) {
        resetDirtyItem(item, /*recursive=*/itemHasChildren);
        return;
    }

    bool wasDirtyParentSceneTransform = item->d_ptr->dirtySceneTransform;
    const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable();
    if (wasDirtyParentSceneTransform && !itemIsUntransformable) {
        item->d_ptr->updateSceneTransformFromParent();
        Q_ASSERT(!item->d_ptr->dirtySceneTransform);
    }

    const bool wasDirtyParentViewBoundingRects = item->d_ptr->paintedViewBoundingRectsNeedRepaint;
    if (itemIsFullyTransparent || !itemHasContents || dirtyAncestorContainsChildren) {
        // Make sure we don't process invisible items or items with no content.
        item->d_ptr->dirty = 0;
        item->d_ptr->fullUpdatePending = 0;
        // Might have a dirty view bounding rect otherwise.
        if (itemIsFullyTransparent || !itemHasContents)
            item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0;
    }

    if (!hasSceneRect && item->d_ptr->geometryChanged && item->d_ptr->visible) {
        // Update growingItemsBoundingRect.
        if (item->d_ptr->sceneTransformTranslateOnly) {
            growingItemsBoundingRect |= item->boundingRect().translated(item->d_ptr->sceneTransform.dx(),
                                                                        item->d_ptr->sceneTransform.dy());
        } else {
            growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(item->boundingRect());
        }
    }

    // Process item.
    if (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
        const bool useCompatUpdate = views.isEmpty() || isSignalConnected(changedSignalIndex);
        const QRectF itemBoundingRect = adjustedItemEffectiveBoundingRect(item);

        if (useCompatUpdate && !itemIsUntransformable && qFuzzyIsNull(item->boundingRegionGranularity())) {
            // This block of code is kept for compatibility. Since 4.5, by default
            // QGraphicsView does not connect the signal and we use the below
            // method of delivering updates.
            if (item->d_ptr->sceneTransformTranslateOnly) {
                q->update(itemBoundingRect.translated(item->d_ptr->sceneTransform.dx(),
                                                      item->d_ptr->sceneTransform.dy()));
            } else {
                QRectF rect = item->d_ptr->sceneTransform.mapRect(itemBoundingRect);
                if (!rect.isEmpty())
                    q->update(rect);
            }
        } else {
            QRectF dirtyRect;
            bool uninitializedDirtyRect = true;

            for (int j = 0; j < views.size(); ++j) {
                QGraphicsView *view = views.at(j);
                QGraphicsViewPrivate *viewPrivate = view->d_func();
                QRect &paintedViewBoundingRect = item->d_ptr->paintedViewBoundingRects[viewPrivate->viewport];
                if (viewPrivate->fullUpdatePending
                    || viewPrivate->viewportUpdateMode == QGraphicsView::NoViewportUpdate) {
                    // Okay, if we have a full update pending or no viewport update, this item's
                    // paintedViewBoundingRect  will be updated correctly in the next paintEvent if
                    // it is inside the viewport, but for now we can pretend that it is outside.
                    paintedViewBoundingRect = QRect(-1, -1, -1, -1);
                    continue;
                }

                if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
                    paintedViewBoundingRect.translate(viewPrivate->dirtyScrollOffset);
                    if (!viewPrivate->updateRect(paintedViewBoundingRect))
                        paintedViewBoundingRect = QRect(-1, -1, -1, -1); // Outside viewport.
                }

                if (!item->d_ptr->dirty)
                    continue;

                if (!item->d_ptr->paintedViewBoundingRectsNeedRepaint
                    && paintedViewBoundingRect.x() == -1 && paintedViewBoundingRect.y() == -1
                    && paintedViewBoundingRect.width() == -1 && paintedViewBoundingRect.height() == -1) {
                    continue; // Outside viewport.
                }

                if (uninitializedDirtyRect) {
                    dirtyRect = itemBoundingRect;
                    if (!item->d_ptr->fullUpdatePending) {
                        _q_adjustRect(&item->d_ptr->needsRepaint);
                        dirtyRect &= item->d_ptr->needsRepaint;
                    }
                    uninitializedDirtyRect = false;
                }

                if (dirtyRect.isEmpty())
                    continue; // Discard updates outside the bounding rect.

                if (!updateHelper(viewPrivate, item->d_ptr.data(), dirtyRect, itemIsUntransformable)
                    && item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
                    paintedViewBoundingRect = QRect(-1, -1, -1, -1); // Outside viewport.
                }
            }
        }
    }

    // Process children.
    if (itemHasChildren && item->d_ptr->dirtyChildren) {
        const bool itemClipsChildrenToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape;
        // Items with no content are threated as 'dummy' items which means they are never drawn and
        // 'processed', so the painted view bounding rect is never up-to-date. This means that whenever
        // such an item changes geometry, its children have to take care of the update regardless
        // of whether the item clips children to shape or not.
        const bool bypassUpdateClip = !itemHasContents && wasDirtyParentViewBoundingRects;
        if (itemClipsChildrenToShape && !bypassUpdateClip) {
            // Make sure child updates are clipped to the item's bounding rect.
            for (int i = 0; i < views.size(); ++i)
                views.at(i)->d_func()->setUpdateClip(item);
        }
        if (!dirtyAncestorContainsChildren) {
            dirtyAncestorContainsChildren = item->d_ptr->fullUpdatePending
                                            && itemClipsChildrenToShape;
        }
        const bool allChildrenDirty = item->d_ptr->allChildrenDirty;
        const bool parentIgnoresVisible = item->d_ptr->ignoreVisible;
        const bool parentIgnoresOpacity = item->d_ptr->ignoreOpacity;
        for (int i = 0; i < item->d_ptr->children.size(); ++i) {
            QGraphicsItem *child = item->d_ptr->children.at(i);
            if (wasDirtyParentSceneTransform)
                child->d_ptr->dirtySceneTransform = 1;
            if (wasDirtyParentViewBoundingRects)
                child->d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
            if (parentIgnoresVisible)
                child->d_ptr->ignoreVisible = 1;
            if (parentIgnoresOpacity)
                child->d_ptr->ignoreOpacity = 1;
            if (allChildrenDirty) {
                child->d_ptr->dirty = 1;
                child->d_ptr->fullUpdatePending = 1;
                child->d_ptr->dirtyChildren = 1;
                child->d_ptr->allChildrenDirty = 1;
            }
            processDirtyItemsRecursive(child, dirtyAncestorContainsChildren, opacity);
        }

        if (itemClipsChildrenToShape) {
            // Reset updateClip.
            for (int i = 0; i < views.size(); ++i)
                views.at(i)->d_func()->setUpdateClip(0);
        }
    } else if (wasDirtyParentSceneTransform) {
        item->d_ptr->invalidateChildrenSceneTransform();
    }

    resetDirtyItem(item);
}

/*!
    \obsolete

    Paints the given \a items using the provided \a painter, after the
    background has been drawn, and before the foreground has been
    drawn.  All painting is done in \e scene coordinates. Before
    drawing each item, the painter must be transformed using
    QGraphicsItem::sceneTransform().

    The \a options parameter is the list of style option objects for
    each item in \a items. The \a numItems parameter is the number of
    items in \a items and options in \a options. The \a widget
    parameter is optional; if specified, it should point to the widget
    that is being painted on.

    The default implementation prepares the painter matrix, and calls
    QGraphicsItem::paint() on all items. Reimplement this function to
    provide custom painting of all items for the scene; gaining
    complete control over how each item is drawn. In some cases this
    can increase drawing performance significantly.

    Example:

    \snippet doc/src/snippets/graphicssceneadditemsnippet.cpp 0

    Since Qt 4.6, this function is not called anymore unless
    the QGraphicsView::IndirectPainting flag is given as an Optimization
    flag.

    \sa drawBackground(), drawForeground()
*/
void QGraphicsScene::drawItems(QPainter *painter,
                               int numItems,
                               QGraphicsItem *items[],
                               const QStyleOptionGraphicsItem options[], QWidget *widget)
{
    Q_D(QGraphicsScene);
    // Make sure we don't have unpolished items before we draw.
    if (!d->unpolishedItems.isEmpty())
        d->_q_polishItems();

    const qreal opacity = painter->opacity();
    QTransform viewTransform = painter->worldTransform();
    Q_UNUSED(options);

    // Determine view, expose and flags.
    QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0;
    QRegion *expose = 0;
    const quint32 oldRectAdjust = d->rectAdjust;
    if (view) {
        d->updateAll = false;
        expose = &view->d_func()->exposedRegion;
        if (view->d_func()->optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
            d->rectAdjust = 1;
        else
            d->rectAdjust = 2;
    }

    // Find all toplevels, they are already sorted.
    QList<QGraphicsItem *> topLevelItems;
    for (int i = 0; i < numItems; ++i) {
        QGraphicsItem *item = items[i]->topLevelItem();
        if (!item->d_ptr->itemDiscovered) {
            topLevelItems << item;
            item->d_ptr->itemDiscovered = 1;
            d->drawSubtreeRecursive(item, painter, &viewTransform, expose, widget);
        }
    }

    d->rectAdjust = oldRectAdjust;
    // Reset discovery bits.
    for (int i = 0; i < topLevelItems.size(); ++i)
        topLevelItems.at(i)->d_ptr->itemDiscovered = 0;

    painter->setWorldTransform(viewTransform);
    painter->setOpacity(opacity);
}

/*!
    \since 4.4

    Finds a new widget to give the keyboard focus to, as appropriate for Tab
    and Shift+Tab, and returns true if it can find a new widget, or false if
    it cannot. If \a next is true, this function searches forward; if \a next
    is false, it searches backward.

    You can reimplement this function in a subclass of QGraphicsScene to
    provide fine-grained control over how tab focus passes inside your
    scene. The default implementation is based on the tab focus chain defined
    by QGraphicsWidget::setTabOrder().
*/
bool QGraphicsScene::focusNextPrevChild(bool next)
{
    Q_D(QGraphicsScene);

    QGraphicsItem *item = focusItem();
    if (item && !item->isWidget()) {
        // Tab out of the scene.
        return false;
    }
    if (!item) {
        if (d->lastFocusItem && !d->lastFocusItem->isWidget()) {
            // Restore focus to the last focusable non-widget item that had
            // focus.
            setFocusItem(d->lastFocusItem, next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
            return true;
        }
    }
    if (!d->tabFocusFirst) {
        // No widgets...
        return false;
    }

    // The item must be a widget.
    QGraphicsWidget *widget = 0;
    if (!item) {
        widget = next ? d->tabFocusFirst : d->tabFocusFirst->d_func()->focusPrev;
    } else {
        QGraphicsWidget *test = static_cast<QGraphicsWidget *>(item);
        widget = next ? test->d_func()->focusNext : test->d_func()->focusPrev;
        if ((next && widget == d->tabFocusFirst) || (!next && widget == d->tabFocusFirst->d_func()->focusPrev))
            return false;
    }
    QGraphicsWidget *widgetThatHadFocus = widget;

    // Run around the focus chain until we find a widget that can take tab focus.
    do {
        if (widget->flags() & QGraphicsItem::ItemIsFocusable
            && widget->isEnabled() && widget->isVisibleTo(0)
            && (widget->focusPolicy() & Qt::TabFocus)
            && (!item || !item->isPanel() || item->isAncestorOf(widget))
            ) {
            setFocusItem(widget, next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
            return true;
        }
        widget = next ? widget->d_func()->focusNext : widget->d_func()->focusPrev;
        if ((next && widget == d->tabFocusFirst) || (!next && widget == d->tabFocusFirst->d_func()->focusPrev))
            return false;
    } while (widget != widgetThatHadFocus);

    return false;
}

/*!
    \fn QGraphicsScene::changed(const QList<QRectF> &region)

    This signal is emitted by QGraphicsScene when control reaches the
    event loop, if the scene content changes. The \a region parameter
    contains a list of scene rectangles that indicate the area that
    has been changed.

    \sa QGraphicsView::updateScene()
*/

/*!
    \fn QGraphicsScene::sceneRectChanged(const QRectF &rect)

    This signal is emitted by QGraphicsScene whenever the scene rect changes.
    The \a rect parameter is the new scene rectangle.

    \sa QGraphicsView::updateSceneRect()
*/

/*!
    \fn QGraphicsScene::selectionChanged()
    \since 4.3

    This signal is emitted by QGraphicsScene whenever the selection
    changes. You can call selectedItems() to get the new list of selected
    items.

    The selection changes whenever an item is selected or unselected, a
    selection area is set, cleared or otherwise changed, if a preselected item
    is added to the scene, or if a selected item is removed from the scene.

    QGraphicsScene emits this signal only once for group selection operations.
    For example, if you set a selection area, select or unselect a
    QGraphicsItemGroup, or if you add or remove from the scene a parent item
    that contains several selected items, selectionChanged() is emitted only
    once after the operation has completed (instead of once for each item).

    \sa setSelectionArea(), selectedItems(), QGraphicsItem::setSelected()
*/

/*!
    \since 4.4

    Returns the scene's style, or the same as QApplication::style() if the
    scene has not been explicitly assigned a style.

    \sa setStyle()
*/
QStyle *QGraphicsScene::style() const
{
    Q_D(const QGraphicsScene);
    // ### This function, and the use of styles in general, is non-reentrant.
    return d->style ? d->style : QApplication::style();
}

/*!
    \since 4.4

    Sets or replaces the style of the scene to \a style, and reparents the
    style to this scene. Any previously assigned style is deleted. The scene's
    style defaults to QApplication::style(), and serves as the default for all
    QGraphicsWidget items in the scene.

    Changing the style, either directly by calling this function, or
    indirectly by calling QApplication::setStyle(), will automatically update
    the style for all widgets in the scene that do not have a style explicitly
    assigned to them.

    If \a style is 0, QGraphicsScene will revert to QApplication::style().

    \sa style()
*/
void QGraphicsScene::setStyle(QStyle *style)
{
    Q_D(QGraphicsScene);
    // ### This function, and the use of styles in general, is non-reentrant.
    if (style == d->style)
        return;

    // Delete the old style,
    delete d->style;
    if ((d->style = style))
        d->style->setParent(this);

    // Notify the scene.
    QEvent event(QEvent::StyleChange);
    QApplication::sendEvent(this, &event);

    // Notify all widgets that don't have a style explicitly set.
    foreach (QGraphicsItem *item, items()) {
        if (item->isWidget()) {
            QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
            if (!widget->testAttribute(Qt::WA_SetStyle))
                QApplication::sendEvent(widget, &event);
        }
    }
}

/*!
    \property QGraphicsScene::font
    \since 4.4
    \brief the scene's default font

    This property provides the scene's font. The scene font defaults to,
    and resolves all its entries from, QApplication::font.

    If the scene's font changes, either directly through setFont() or
    indirectly when the application font changes, QGraphicsScene first
    sends itself a \l{QEvent::FontChange}{FontChange} event, and it then
    sends \l{QEvent::FontChange}{FontChange} events to all top-level
    widget items in the scene. These items respond by resolving their own
    fonts to the scene, and they then notify their children, who again
    notify their children, and so on, until all widget items have updated
    their fonts.

    Changing the scene font, (directly or indirectly through
    QApplication::setFont(),) automatically schedules a redraw the entire
    scene.

    \sa QWidget::font, QApplication::setFont(), palette, style()
*/
QFont QGraphicsScene::font() const
{
    Q_D(const QGraphicsScene);
    return d->font;
}
void QGraphicsScene::setFont(const QFont &font)
{
    Q_D(QGraphicsScene);
    QFont naturalFont = QApplication::font();
    naturalFont.resolve(0);
    QFont resolvedFont = font.resolve(naturalFont);
    d->setFont_helper(resolvedFont);
}

/*!
    \property QGraphicsScene::palette
    \since 4.4
    \brief the scene's default palette

    This property provides the scene's palette. The scene palette defaults to,
    and resolves all its entries from, QApplication::palette.

    If the scene's palette changes, either directly through setPalette() or
    indirectly when the application palette changes, QGraphicsScene first
    sends itself a \l{QEvent::PaletteChange}{PaletteChange} event, and it then
    sends \l{QEvent::PaletteChange}{PaletteChange} events to all top-level
    widget items in the scene. These items respond by resolving their own
    palettes to the scene, and they then notify their children, who again
    notify their children, and so on, until all widget items have updated
    their palettes.

    Changing the scene palette, (directly or indirectly through
    QApplication::setPalette(),) automatically schedules a redraw the entire
    scene.

    \sa QWidget::palette, QApplication::setPalette(), font, style()
*/
QPalette QGraphicsScene::palette() const
{
    Q_D(const QGraphicsScene);
    return d->palette;
}
void QGraphicsScene::setPalette(const QPalette &palette)
{
    Q_D(QGraphicsScene);
    QPalette naturalPalette = QApplication::palette();
    naturalPalette.resolve(0);
    QPalette resolvedPalette = palette.resolve(naturalPalette);
    d->setPalette_helper(resolvedPalette);
}

/*!
    \since 4.6

    Returns true if the scene is active (e.g., it's viewed by
    at least one QGraphicsView that is active); otherwise returns false.

    \sa QGraphicsItem::isActive(), QWidget::isActiveWindow()
*/
bool QGraphicsScene::isActive() const
{
    Q_D(const QGraphicsScene);
    return d->activationRefCount > 0;
}

/*!
    \since 4.6
    Returns the current active panel, or 0 if no panel is currently active.

    \sa QGraphicsScene::setActivePanel()
*/
QGraphicsItem *QGraphicsScene::activePanel() const
{
    Q_D(const QGraphicsScene);
    return d->activePanel;
}

/*!
    \since 4.6
    Activates \a item, which must be an item in this scene. You
    can also pass 0 for \a item, in which case QGraphicsScene will
    deactivate any currently active panel.

    If the scene is currently inactive, \a item remains inactive until the
    scene becomes active (or, ir \a item is 0, no item will be activated).

    \sa activePanel(), isActive(), QGraphicsItem::isActive()
*/
void QGraphicsScene::setActivePanel(QGraphicsItem *item)
{
    Q_D(QGraphicsScene);
    d->setActivePanelHelper(item, false);
}

/*!
    \since 4.4

    Returns the current active window, or 0 if no window is currently
    active.

    \sa QGraphicsScene::setActiveWindow()
*/
QGraphicsWidget *QGraphicsScene::activeWindow() const
{
    Q_D(const QGraphicsScene);
    if (d->activePanel && d->activePanel->isWindow())
        return static_cast<QGraphicsWidget *>(d->activePanel);
    return 0;
}

/*!
    \since 4.4
    Activates \a widget, which must be a widget in this scene. You can also
    pass 0 for \a widget, in which case QGraphicsScene will deactivate any
    currently active window.

    \sa activeWindow(), QGraphicsWidget::isActiveWindow()
*/
void QGraphicsScene::setActiveWindow(QGraphicsWidget *widget)
{
    if (widget && widget->scene() != this) {
        qWarning("QGraphicsScene::setActiveWindow: widget %p must be part of this scene",
                 widget);
        return;
    }

    // Activate the widget's panel (all windows are panels).
    QGraphicsItem *panel = widget ? widget->panel() : 0;
    setActivePanel(panel);

    // Raise
    if (panel) {
        QList<QGraphicsItem *> siblingWindows;
        QGraphicsItem *parent = panel->parentItem();
        // Raise ### inefficient for toplevels
        foreach (QGraphicsItem *sibling, parent ? parent->children() : items()) {
            if (sibling != panel && sibling->isWindow())
                siblingWindows << sibling;
        }

        // Find the highest z value.
        qreal z = panel->zValue();
        for (int i = 0; i < siblingWindows.size(); ++i)
            z = qMax(z, siblingWindows.at(i)->zValue());

        // This will probably never overflow.
        const qreal litt = qreal(0.001);
        panel->setZValue(z + litt);
    }
}

/*!
    \since 4.6

    Sends event \a event to item \a item through possible event filters.

    The event is sent only if the item is enabled.

    Returns \c false if the event was filtered or if the item is disabled.
    Otherwise returns the value that was returned from the event handler.

    \sa QGraphicsItem::sceneEvent(), QGraphicsItem::sceneEventFilter()
*/
bool QGraphicsScene::sendEvent(QGraphicsItem *item, QEvent *event)
{
    Q_D(QGraphicsScene);
    if (!item) {
        qWarning("QGraphicsScene::sendEvent: cannot send event to a null item");
        return false;
    }
    if (item->scene() != this) {
        qWarning("QGraphicsScene::sendEvent: item %p's scene (%p)"
                 " is different from this scene (%p)",
                 item, item->scene(), this);
        return false;
    }
    return d->sendEvent(item, event);
}

void QGraphicsScenePrivate::addView(QGraphicsView *view)
{
    views << view;
#ifndef QT_NO_GESTURES
    foreach (Qt::GestureType gesture, grabbedGestures.keys())
        view->viewport()->grabGesture(gesture);
#endif
}

void QGraphicsScenePrivate::removeView(QGraphicsView *view)
{
    views.removeAll(view);
}

void QGraphicsScenePrivate::updateTouchPointsForItem(QGraphicsItem *item, QTouchEvent *touchEvent)
{
    QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints();
    for (int i = 0; i < touchPoints.count(); ++i) {
        QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
        touchPoint.setRect(item->mapFromScene(touchPoint.sceneRect()).boundingRect());
        touchPoint.setStartPos(item->d_ptr->genericMapFromScene(touchPoint.startScenePos(), touchEvent->widget()));
        touchPoint.setLastPos(item->d_ptr->genericMapFromScene(touchPoint.lastScenePos(), touchEvent->widget()));
    }
    touchEvent->setTouchPoints(touchPoints);
}

int QGraphicsScenePrivate::findClosestTouchPointId(const QPointF &scenePos)
{
    int closestTouchPointId = -1;
    qreal closestDistance = qreal(0.);
    foreach (const QTouchEvent::TouchPoint &touchPoint, sceneCurrentTouchPoints) {
        qreal distance = QLineF(scenePos, touchPoint.scenePos()).length();
        if (closestTouchPointId == -1|| distance < closestDistance) {
            closestTouchPointId = touchPoint.id();
            closestDistance = distance;
        }
    }
    return closestTouchPointId;
}

void QGraphicsScenePrivate::touchEventHandler(QTouchEvent *sceneTouchEvent)
{
    typedef QPair<Qt::TouchPointStates, QList<QTouchEvent::TouchPoint> > StatesAndTouchPoints;
    QHash<QGraphicsItem *, StatesAndTouchPoints> itemsNeedingEvents;

    for (int i = 0; i < sceneTouchEvent->touchPoints().count(); ++i) {
        const QTouchEvent::TouchPoint &touchPoint = sceneTouchEvent->touchPoints().at(i);

        // update state
        QGraphicsItem *item = 0;
        if (touchPoint.state() == Qt::TouchPointPressed) {
            if (sceneTouchEvent->deviceType() == QTouchEvent::TouchPad) {
                // on touch-pad devices, send all touch points to the same item
                item = itemForTouchPointId.isEmpty()
                       ? 0
                       : itemForTouchPointId.constBegin().value();
            }

            if (!item) {
                // determine which item this touch point will go to
                cachedItemsUnderMouse = itemsAtPosition(touchPoint.screenPos().toPoint(),
                                                        touchPoint.scenePos(),
                                                        sceneTouchEvent->widget());
                item = cachedItemsUnderMouse.isEmpty() ? 0 : cachedItemsUnderMouse.first();
            }

            if (sceneTouchEvent->deviceType() == QTouchEvent::TouchScreen) {
                // on touch-screens, combine this touch point with the closest one we find
                int closestTouchPointId = findClosestTouchPointId(touchPoint.scenePos());
                QGraphicsItem *closestItem = itemForTouchPointId.value(closestTouchPointId);
                if (!item || (closestItem && cachedItemsUnderMouse.contains(closestItem)))
                    item = closestItem;
            }
            if (!item)
                continue;

            itemForTouchPointId.insert(touchPoint.id(), item);
            sceneCurrentTouchPoints.insert(touchPoint.id(), touchPoint);
        } else if (touchPoint.state() == Qt::TouchPointReleased) {
            item = itemForTouchPointId.take(touchPoint.id());
            if (!item)
                continue;

            sceneCurrentTouchPoints.remove(touchPoint.id());
        } else {
            item = itemForTouchPointId.value(touchPoint.id());
            if (!item)
                continue;
            Q_ASSERT(sceneCurrentTouchPoints.contains(touchPoint.id()));
            sceneCurrentTouchPoints[touchPoint.id()] = touchPoint;
        }

        StatesAndTouchPoints &statesAndTouchPoints = itemsNeedingEvents[item];
        statesAndTouchPoints.first |= touchPoint.state();
        statesAndTouchPoints.second.append(touchPoint);
    }

    if (itemsNeedingEvents.isEmpty()) {
        sceneTouchEvent->accept();
        return;
    }

    bool ignoreSceneTouchEvent = true;
    QHash<QGraphicsItem *, StatesAndTouchPoints>::ConstIterator it = itemsNeedingEvents.constBegin();
    const QHash<QGraphicsItem *, StatesAndTouchPoints>::ConstIterator end = itemsNeedingEvents.constEnd();
    for (; it != end; ++it) {
        QGraphicsItem *item = it.key();

        (void) item->isBlockedByModalPanel(&item);

        // determine event type from the state mask
        QEvent::Type eventType;
        switch (it.value().first) {
        case Qt::TouchPointPressed:
            // all touch points have pressed state
            eventType = QEvent::TouchBegin;
            break;
        case Qt::TouchPointReleased:
            // all touch points have released state
            eventType = QEvent::TouchEnd;
            break;
        case Qt::TouchPointStationary:
            // don't send the event if nothing changed
            continue;
        default:
            // all other combinations
            eventType = QEvent::TouchUpdate;
            break;
        }

        QTouchEvent touchEvent(eventType);
        touchEvent.setWidget(sceneTouchEvent->widget());
        touchEvent.setDeviceType(sceneTouchEvent->deviceType());
        touchEvent.setModifiers(sceneTouchEvent->modifiers());
        touchEvent.setTouchPointStates(it.value().first);
        touchEvent.setTouchPoints(it.value().second);

        switch (touchEvent.type()) {
        case QEvent::TouchBegin:
        {
            // if the TouchBegin handler recurses, we assume that means the event
            // has been implicitly accepted and continue to send touch events
            item->d_ptr->acceptedTouchBeginEvent = true;
            bool res = sendTouchBeginEvent(item, &touchEvent)
                       && touchEvent.isAccepted();
            if (!res) {
                // forget about these touch points, we didn't handle them
                for (int i = 0; i < touchEvent.touchPoints().count(); ++i) {
                    const QTouchEvent::TouchPoint &touchPoint = touchEvent.touchPoints().at(i);
                    itemForTouchPointId.remove(touchPoint.id());
                    sceneCurrentTouchPoints.remove(touchPoint.id());
                }
                ignoreSceneTouchEvent = false;
            }
            break;
        }
        default:
            if (item->d_ptr->acceptedTouchBeginEvent) {
                updateTouchPointsForItem(item, &touchEvent);
                (void) sendEvent(item, &touchEvent);
                ignoreSceneTouchEvent = false;
            }
            break;
        }
    }
    sceneTouchEvent->setAccepted(ignoreSceneTouchEvent);
}

bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEvent *touchEvent)
{
    Q_Q(QGraphicsScene);

    if (cachedItemsUnderMouse.isEmpty() || cachedItemsUnderMouse.first() != origin) {
        const QTouchEvent::TouchPoint &firstTouchPoint = touchEvent->touchPoints().first();
        cachedItemsUnderMouse = itemsAtPosition(firstTouchPoint.screenPos().toPoint(),
                                                firstTouchPoint.scenePos(),
                                                touchEvent->widget());
    }
    Q_ASSERT(cachedItemsUnderMouse.first() == origin);

    // Set focus on the topmost enabled item that can take focus.
    bool setFocus = false;

    foreach (QGraphicsItem *item, cachedItemsUnderMouse) {
        if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) {
            if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
                setFocus = true;
                if (item != q->focusItem())
                    q->setFocusItem(item, Qt::MouseFocusReason);
                break;
            }
        }
        if (item->isPanel())
            break;
        if (item->d_ptr->flags & QGraphicsItem::ItemStopsClickFocusPropagation)
            break;
        if (item->d_ptr->flags & QGraphicsItem::ItemStopsFocusHandling) {
            // Make sure we don't clear focus.
            setFocus = true;
            break;
        }
    }

    // If nobody could take focus, clear it.
    if (!stickyFocus && !setFocus)
        q->setFocusItem(0, Qt::MouseFocusReason);

    bool res = false;
    bool eventAccepted = touchEvent->isAccepted();
    foreach (QGraphicsItem *item, cachedItemsUnderMouse) {
        // first, try to deliver the touch event
        updateTouchPointsForItem(item, touchEvent);
        bool acceptTouchEvents = item->acceptTouchEvents();
        touchEvent->setAccepted(acceptTouchEvents);
        res = acceptTouchEvents && sendEvent(item, touchEvent);
        eventAccepted = touchEvent->isAccepted();
        if (itemForTouchPointId.value(touchEvent->touchPoints().first().id()) == 0) {
            // item was deleted
            item = 0;
        } else {
            item->d_ptr->acceptedTouchBeginEvent = (res && eventAccepted);
        }
        touchEvent->spont = false;
        if (res && eventAccepted) {
            // the first item to accept the TouchBegin gets an implicit grab.
            for (int i = 0; i < touchEvent->touchPoints().count(); ++i) {
                const QTouchEvent::TouchPoint &touchPoint = touchEvent->touchPoints().at(i);
                itemForTouchPointId[touchPoint.id()] = item; // can be zero
            }
            break;
        }
        if (item && item->isPanel())
            break;
    }

    touchEvent->setAccepted(eventAccepted);
    return res;
}

void QGraphicsScenePrivate::enableTouchEventsOnViews()
{
    foreach (QGraphicsView *view, views)
        view->viewport()->setAttribute(Qt::WA_AcceptTouchEvents, true);
}

void QGraphicsScenePrivate::updateInputMethodSensitivityInViews()
{
    for (int i = 0; i < views.size(); ++i)
        views.at(i)->d_func()->updateInputMethodSensitivity();
}

void QGraphicsScenePrivate::enterModal(QGraphicsItem *panel, QGraphicsItem::PanelModality previousModality)
{
    Q_Q(QGraphicsScene);
    Q_ASSERT(panel && panel->isPanel());

    QGraphicsItem::PanelModality panelModality = panel->d_ptr->panelModality;
    if (previousModality != QGraphicsItem::NonModal) {
        // the panel is changing from one modality type to another... temporarily set it back so
        // that blockedPanels is populated correctly
        panel->d_ptr->panelModality = previousModality;
    }

    QSet<QGraphicsItem *> blockedPanels;
    QList<QGraphicsItem *> items = q->items(); // ### store panels separately
    for (int i = 0; i < items.count(); ++i) {
        QGraphicsItem *item = items.at(i);
        if (item->isPanel() && item->isBlockedByModalPanel())
            blockedPanels.insert(item);
    }
    // blockedPanels contains all currently blocked panels

    if (previousModality != QGraphicsItem::NonModal) {
        // reset the modality to the proper value, since we changed it above
        panel->d_ptr->panelModality = panelModality;
        // remove this panel so that it will be reinserted at the front of the stack
        modalPanels.removeAll(panel);
    }

    modalPanels.prepend(panel);

    if (!hoverItems.isEmpty()) {
        // send GraphicsSceneHoverLeave events to newly blocked hoverItems
        QGraphicsSceneHoverEvent hoverEvent;
        hoverEvent.setScenePos(lastSceneMousePos);
        dispatchHoverEvent(&hoverEvent);
    }

    if (!mouseGrabberItems.isEmpty() && lastMouseGrabberItemHasImplicitMouseGrab) {
        QGraphicsItem *item = mouseGrabberItems.last();
        if (item->isBlockedByModalPanel())
            ungrabMouse(item, /*itemIsDying =*/ false);
    }

    QEvent windowBlockedEvent(QEvent::WindowBlocked);
    QEvent windowUnblockedEvent(QEvent::WindowUnblocked);
    for (int i = 0; i < items.count(); ++i) {
        QGraphicsItem *item = items.at(i);
        if (item->isPanel()) {
            if (!blockedPanels.contains(item) && item->isBlockedByModalPanel()) {
                // send QEvent::WindowBlocked to newly blocked panels
                sendEvent(item, &windowBlockedEvent);
            } else if (blockedPanels.contains(item) && !item->isBlockedByModalPanel()) {
                // send QEvent::WindowUnblocked to unblocked panels when downgrading
                // a panel from SceneModal to PanelModal
                sendEvent(item, &windowUnblockedEvent);
            }
        }
    }
}

void QGraphicsScenePrivate::leaveModal(QGraphicsItem *panel)
{
    Q_Q(QGraphicsScene);
    Q_ASSERT(panel && panel->isPanel());

    QSet<QGraphicsItem *> blockedPanels;
    QList<QGraphicsItem *> items = q->items(); // ### same as above
    for (int i = 0; i < items.count(); ++i) {
        QGraphicsItem *item = items.at(i);
        if (item->isPanel() && item->isBlockedByModalPanel())
            blockedPanels.insert(item);
    }

    modalPanels.removeAll(panel);

    QEvent e(QEvent::WindowUnblocked);
    for (int i = 0; i < items.count(); ++i) {
        QGraphicsItem *item = items.at(i);
        if (item->isPanel() && blockedPanels.contains(item) && !item->isBlockedByModalPanel())
            sendEvent(item, &e);
    }

    // send GraphicsSceneHoverEnter events to newly unblocked items
    QGraphicsSceneHoverEvent hoverEvent;
    hoverEvent.setScenePos(lastSceneMousePos);
    dispatchHoverEvent(&hoverEvent);
}

#ifndef QT_NO_GESTURES
void QGraphicsScenePrivate::gestureTargetsAtHotSpots(const QSet<QGesture *> &gestures,
                                              Qt::GestureFlag flag,
                                              QHash<QGraphicsObject *, QSet<QGesture *> > *targets,
                                              QSet<QGraphicsObject *> *itemsSet,
                                              QSet<QGesture *> *normal,
                                              QSet<QGesture *> *conflicts)
{
    QSet<QGesture *> normalGestures; // that are not in conflicted state.
    foreach (QGesture *gesture, gestures) {
        if (!gesture->hasHotSpot())
            continue;
        const Qt::GestureType gestureType = gesture->gestureType();
        QList<QGraphicsItem *> items = itemsAtPosition(QPoint(), gesture->d_func()->sceneHotSpot, 0);
        for (int j = 0; j < items.size(); ++j) {
            QGraphicsItem *item = items.at(j);

            // Check if the item is blocked by a modal panel and use it as
            // a target instead of this item.
            (void) item->isBlockedByModalPanel(&item);

            if (QGraphicsObject *itemobj = item->toGraphicsObject()) {
                QGraphicsItemPrivate *d = item->QGraphicsItem::d_func();
                QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator it =
                        d->gestureContext.find(gestureType);
                if (it != d->gestureContext.end() && (!flag || (it.value() & flag))) {
                    if (normalGestures.contains(gesture)) {
                        normalGestures.remove(gesture);
                        if (conflicts)
                            conflicts->insert(gesture);
                    } else {
                        normalGestures.insert(gesture);
                    }
                    if (targets)
                        (*targets)[itemobj].insert(gesture);
                    if (itemsSet)
                        (*itemsSet).insert(itemobj);
                }
            }
            // Don't propagate through panels.
            if (item->isPanel())
                break;
        }
    }
    if (normal)
        *normal = normalGestures;
}

void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event)
{
    QWidget *viewport = event->widget();
    if (!viewport)
        return;
    QGraphicsView *graphicsView = qobject_cast<QGraphicsView *>(viewport->parent());
    if (!graphicsView)
        return;

    QList<QGesture *> allGestures = event->gestures();
    DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
            << "Gestures:" <<  allGestures;

    QSet<QGesture *> startedGestures;
    QPoint delta = viewport->mapFromGlobal(QPoint());
    QTransform toScene = QTransform::fromTranslate(delta.x(), delta.y())
                         * graphicsView->viewportTransform().inverted();
    foreach (QGesture *gesture, allGestures) {
        // cache scene coordinates of the hot spot
        if (gesture->hasHotSpot()) {
            gesture->d_func()->sceneHotSpot = toScene.map(gesture->hotSpot());
        } else {
            gesture->d_func()->sceneHotSpot = QPointF();
        }

        QGraphicsObject *target = gestureTargets.value(gesture, 0);
        if (!target) {
            // when we are not in started mode but don't have a target
            // then the only one interested in gesture is the view/scene
            if (gesture->state() == Qt::GestureStarted)
                startedGestures.insert(gesture);
        }
    }

    if (!startedGestures.isEmpty()) {
        QSet<QGesture *> normalGestures; // that have just one target
        QSet<QGesture *> conflictedGestures; // that have multiple possible targets
        gestureTargetsAtHotSpots(startedGestures, Qt::GestureFlag(0), &cachedItemGestures, 0,
                                 &normalGestures, &conflictedGestures);
        cachedTargetItems = cachedItemGestures.keys();
        qSort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst);
        DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
                << "Normal gestures:" << normalGestures
                << "Conflicting gestures:" << conflictedGestures;

        // deliver conflicted gestures as override events AND remember
        // initial gesture targets
        if (!conflictedGestures.isEmpty()) {
            for (int i = 0; i < cachedTargetItems.size(); ++i) {
                QWeakPointer<QGraphicsObject> item = cachedTargetItems.at(i);

                // get gestures to deliver to the current item
                QSet<QGesture *> gestures = conflictedGestures & cachedItemGestures.value(item.data());
                if (gestures.isEmpty())
                    continue;

                DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
                        << "delivering override to"
                        << item.data() << gestures;
                // send gesture override
                QGestureEvent ev(gestures.toList());
                ev.t = QEvent::GestureOverride;
                ev.setWidget(event->widget());
                // mark event and individual gestures as ignored
                ev.ignore();
                foreach(QGesture *g, gestures)
                    ev.setAccepted(g, false);
                sendEvent(item.data(), &ev);
                // mark all accepted gestures to deliver them as normal gesture events
                foreach (QGesture *g, gestures) {
                    if (ev.isAccepted() || ev.isAccepted(g)) {
                        conflictedGestures.remove(g);
                        // mark the item as a gesture target
                        if (item) {
                            gestureTargets.insert(g, item.data());
                            QHash<QGraphicsObject *, QSet<QGesture *> >::iterator it, e;
                            it = cachedItemGestures.begin();
                            e = cachedItemGestures.end();
                            for(; it != e; ++it)
                                it.value().remove(g);
                            cachedItemGestures[item.data()].insert(g);
                        }
                        DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
                                << "override was accepted:"
                                << g << item.data();
                    }
                    // remember the first item that received the override event
                    // as it most likely become a target if no one else accepts
                    // the override event
                    if (!gestureTargets.contains(g) && item)
                        gestureTargets.insert(g, item.data());

                }
                if (conflictedGestures.isEmpty())
                    break;
            }
        }
        // remember the initial target item for each gesture that was not in
        // the conflicted state.
        if (!normalGestures.isEmpty()) {
            for (int i = 0; i < cachedTargetItems.size() && !normalGestures.isEmpty(); ++i) {
                QGraphicsObject *item = cachedTargetItems.at(i);

                // get gestures to deliver to the current item
                foreach (QGesture *g, cachedItemGestures.value(item)) {
                    if (!gestureTargets.contains(g)) {
                        gestureTargets.insert(g, item);
                        normalGestures.remove(g);
                    }
                }
            }
        }
    }


    // deliver all gesture events
    QSet<QGesture *> undeliveredGestures;
    QSet<QGesture *> parentPropagatedGestures;
    foreach (QGesture *gesture, allGestures) {
        if (QGraphicsObject *target = gestureTargets.value(gesture, 0)) {
            cachedItemGestures[target].insert(gesture);
            cachedTargetItems.append(target);
            undeliveredGestures.insert(gesture);
            QGraphicsItemPrivate *d = target->QGraphicsItem::d_func();
            const Qt::GestureFlags flags = d->gestureContext.value(gesture->gestureType());
            if (flags & Qt::IgnoredGesturesPropagateToParent)
                parentPropagatedGestures.insert(gesture);
        } else {
            DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
                    << "no target for" << gesture << "at"
                    << gesture->hotSpot() << gesture->d_func()->sceneHotSpot;
        }
    }
    qSort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst);
    for (int i = 0; i < cachedTargetItems.size(); ++i) {
        QWeakPointer<QGraphicsObject> receiver = cachedTargetItems.at(i);
        QSet<QGesture *> gestures =
                undeliveredGestures & cachedItemGestures.value(receiver.data());
        gestures -= cachedAlreadyDeliveredGestures.value(receiver.data());

        if (gestures.isEmpty())
            continue;

        cachedAlreadyDeliveredGestures[receiver.data()] += gestures;
        const bool isPanel = receiver.data()->isPanel();

        DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
                << "delivering to"
                << receiver.data() << gestures;
        QGestureEvent ev(gestures.toList());
        ev.setWidget(event->widget());
        sendEvent(receiver.data(), &ev);
        QSet<QGesture *> ignoredGestures;
        foreach (QGesture *g, gestures) {
            if (!ev.isAccepted() && !ev.isAccepted(g)) {
                // if the gesture was ignored by its target, we will update the
                // targetItems list with a possible target items (items that
                // want to receive partial gestures).
                // ### wont' work if the target was destroyed in the event
                //     we will just stop delivering it.
                if (receiver && receiver.data() == gestureTargets.value(g, 0))
                    ignoredGestures.insert(g);
            } else {
                if (receiver && g->state() == Qt::GestureStarted) {
                    // someone accepted the propagated initial GestureStarted
                    // event, let it be the new target for all following events.
                    gestureTargets[g] = receiver.data();
                }
                undeliveredGestures.remove(g);
            }
        }
        if (undeliveredGestures.isEmpty())
            break;

        // ignoredGestures list is only filled when delivering to the gesture
        // target item, so it is safe to assume item == target.
        if (!ignoredGestures.isEmpty() && !isPanel) {
            // look for new potential targets for gestures that were ignored
            // and should be propagated.

            QSet<QGraphicsObject *> targetsSet = cachedTargetItems.toSet();

            if (receiver) {
                // first if the gesture should be propagated to parents only
                for (QSet<QGesture *>::iterator it = ignoredGestures.begin();
                     it != ignoredGestures.end();) {
                    if (parentPropagatedGestures.contains(*it)) {
                        QGesture *gesture = *it;
                        const Qt::GestureType gestureType = gesture->gestureType();
                        QGraphicsItem *item = receiver.data();
                        while (item) {
                            if (QGraphicsObject *obj = item->toGraphicsObject()) {
                                if (item->d_func()->gestureContext.contains(gestureType)) {
                                    targetsSet.insert(obj);
                                    cachedItemGestures[obj].insert(gesture);
                                }
                            }
                            if (item->isPanel())
                                break;
                            item = item->parentItem();
                        }

                        it = ignoredGestures.erase(it);
                        continue;
                    }
                    ++it;
                }
            }

            gestureTargetsAtHotSpots(ignoredGestures, Qt::ReceivePartialGestures,
                                     &cachedItemGestures, &targetsSet, 0, 0);

            cachedTargetItems = targetsSet.toList();
            qSort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst);
            DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
                    << "new targets:" << cachedTargetItems;
            i = -1; // start delivery again
            continue;
        }
    }

    foreach (QGesture *g, startedGestures) {
        if (g->gestureCancelPolicy() == QGesture::CancelAllInContext) {
            DEBUG() << "lets try to cancel some";
            // find gestures in context in Qt::GestureStarted or Qt::GestureUpdated state and cancel them
            cancelGesturesForChildren(g);
        }
    }

    // forget about targets for gestures that have ended
    foreach (QGesture *g, allGestures) {
        switch (g->state()) {
        case Qt::GestureFinished:
        case Qt::GestureCanceled:
            gestureTargets.remove(g);
            break;
        default:
            break;
        }
    }

    cachedTargetItems.clear();
    cachedItemGestures.clear();
    cachedAlreadyDeliveredGestures.clear();
}

void QGraphicsScenePrivate::cancelGesturesForChildren(QGesture *original)
{
    Q_ASSERT(original);
    QGraphicsItem *originalItem = gestureTargets.value(original);
    if (originalItem == 0) // we only act on accepted gestures, which implies it has a target.
        return;

    // iterate over all active gestures and for each find the owner
    // if the owner is part of our sub-hierarchy, cancel it.

    QSet<QGesture *> canceledGestures;
    QHash<QGesture *, QGraphicsObject *>::Iterator iter = gestureTargets.begin();
    while (iter != gestureTargets.end()) {
        QGraphicsObject *item = iter.value();
        // note that we don't touch the gestures for our originalItem
        if (item != originalItem && originalItem->isAncestorOf(item)) {
            DEBUG() << "  found a gesture to cancel" << iter.key();
            iter.key()->d_func()->state = Qt::GestureCanceled;
            canceledGestures << iter.key();
        }
        ++iter;
    }

    // sort them per target item by cherry picking from almostCanceledGestures and delivering
    QSet<QGesture *> almostCanceledGestures = canceledGestures;
    QSet<QGesture *>::Iterator setIter;
    while (!almostCanceledGestures.isEmpty()) {
        QGraphicsObject *target = 0;
        QSet<QGesture*> gestures;
        setIter = almostCanceledGestures.begin();
        // sort per target item
        while (setIter != almostCanceledGestures.end()) {
            QGraphicsObject *item = gestureTargets.value(*setIter);
            if (target == 0)
                target = item;
            if (target == item) {
                gestures << *setIter;
                setIter = almostCanceledGestures.erase(setIter);
            } else {
                ++setIter;
            }
        }
        Q_ASSERT(target);

        QList<QGesture *> list = gestures.toList();
        QGestureEvent ev(list);
        sendEvent(target, &ev);

        foreach (QGesture *g, list) {
            if (ev.isAccepted() || ev.isAccepted(g))
                gestures.remove(g);
        }

        foreach (QGesture *g, gestures) {
            if (!g->hasHotSpot())
                continue;

            QList<QGraphicsItem *> items = itemsAtPosition(QPoint(), g->d_func()->sceneHotSpot, 0);
            for (int j = 0; j < items.size(); ++j) {
                QGraphicsObject *item = items.at(j)->toGraphicsObject();
                if (!item)
                    continue;
                QGraphicsItemPrivate *d = item->QGraphicsItem::d_func();
                if (d->gestureContext.contains(g->gestureType())) {
                    QList<QGesture *> list;
                    list << g;
                    QGestureEvent ev(list);
                    sendEvent(item, &ev);
                    if (ev.isAccepted() || ev.isAccepted(g))
                        break; // successfully delivered
                }
            }
        }
    }

    QGestureManager *gestureManager = QApplicationPrivate::instance()->gestureManager;
    Q_ASSERT(gestureManager); // it would be very odd if we got called without a manager.
    for (setIter = canceledGestures.begin(); setIter != canceledGestures.end(); ++setIter) {
        gestureManager->recycle(*setIter);
        gestureTargets.remove(*setIter);
    }
}

void QGraphicsScenePrivate::grabGesture(QGraphicsItem *, Qt::GestureType gesture)
{
    (void)QGestureManager::instance(); // create a gesture manager
    if (!grabbedGestures[gesture]++) {
        foreach (QGraphicsView *view, views)
            view->viewport()->grabGesture(gesture);
    }
}

void QGraphicsScenePrivate::ungrabGesture(QGraphicsItem *item, Qt::GestureType gesture)
{
    // we know this can only be an object
    Q_ASSERT(item->d_ptr->isObject);
    QGraphicsObject *obj = static_cast<QGraphicsObject *>(item);
    QGestureManager::instance()->cleanupCachedGestures(obj, gesture);
    if (!--grabbedGestures[gesture]) {
        foreach (QGraphicsView *view, views)
            view->viewport()->ungrabGesture(gesture);
    }
}
#endif // QT_NO_GESTURES

QT_END_NAMESPACE

#include "moc_qgraphicsscene.cpp"

#endif // QT_NO_GRAPHICSVIEW