summaryrefslogtreecommitdiffstats
path: root/mkspecs/tru64-cxx/qplatformdefs.h
blob: aa3a9094f8464b64f6a433f8ed435bb381a9d3e7 (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
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the qmake spec of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#ifndef QPLATFORMDEFS_H
#define QPLATFORMDEFS_H

// Get Qt defines/settings

#include "qglobal.h"

// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs

#include <unistd.h>


// We are hot - unistd.h should have turned on the specific APIs we requested


#ifndef QT_NO_THREAD
#include <pthread.h>
#endif
#include <dirent.h>
#include <fcntl.h>
#include <grp.h>
#include <pwd.h>
#include <signal.h>
#include <dlfcn.h>

#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/ipc.h>
#include <sys/time.h>
#include <sys/select.h>
#include <sys/shm.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <netinet/in.h>
#ifndef QT_NO_IPV6IFNAME
#include <net/if.h>
#endif

#define QT_FOPEN                ::fopen
#define QT_FSEEK                ::fseek
#define QT_FTELL                ::ftell
#define QT_FGETPOS              ::fgetpos
#define QT_FSETPOS              ::fsetpos
#define QT_MMAP                 ::mmap
#define QT_FPOS_T               fpos_t
#define QT_OFF_T                off_t

#define QT_STATBUF		struct stat
#define QT_STATBUF4TSTAT	struct stat
#define QT_STAT			::stat
#define QT_FSTAT		::fstat
#define QT_LSTAT		::lstat
#define QT_STAT_REG		S_IFREG
#define QT_STAT_DIR		S_IFDIR
#define QT_STAT_MASK		S_IFMT
#define QT_STAT_LNK		S_IFLNK
#define QT_SOCKET_CONNECT	::connect
#define QT_SOCKET_BIND		::bind
#define QT_FILENO		fileno
#define QT_OPEN			::open
#define QT_CLOSE		::close
#define QT_TRUNCATE		::truncate
#define QT_FTRUNCATE		::ftruncate
#define QT_LSEEK		::lseek
#define QT_READ			::read
#define QT_WRITE		::write
#define QT_ACCESS		::access
#define QT_GETCWD		::getcwd
#define QT_CHDIR		::chdir
#define QT_MKDIR		::mkdir
#define QT_RMDIR		::rmdir
#define QT_OPEN_LARGEFILE       O_LARGEFILE
#define QT_OPEN_RDONLY		O_RDONLY
#define QT_OPEN_WRONLY		O_WRONLY
#define QT_OPEN_RDWR		O_RDWR
#define QT_OPEN_CREAT		O_CREAT
#define QT_OPEN_TRUNC		O_TRUNC
#define QT_OPEN_APPEND		O_APPEND

#define QT_SIGNAL_RETTYPE	void
#define QT_SIGNAL_ARGS		int
#define QT_SIGNAL_IGNORE	SIG_IGN

#if defined(_XOPEN_SOURCE) && defined(_OSF_SOURCE)
// Not available in the <unistd.h> header file of Tru64 4.0F.
// Fixed in the <unistd.h> header of Tru64 5.0A so we copy/paste from there...
extern "C" int usleep(useconds_t);
#endif

#if defined(_POSIX_PII_SOCKET)
#define QT_SOCKLEN_T		socklen_t
#elif defined(_XOPEN_SOURCE_EXTENDED)
#define QT_SOCKLEN_T		size_t
#else
#define QT_SOCKLEN_T		int
#endif

#if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE-0 >= 400)
// Tru64 5.0 and better
#define QT_SNPRINTF		::snprintf
#define QT_VSNPRINTF		::vsnprintf
#endif


#endif // QPLATFORMDEFS_H
'>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 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qwizard.h"

#ifndef QT_NO_WIZARD

#include "qabstractspinbox.h"
#include "qalgorithms.h"
#include "qapplication.h"
#include "qboxlayout.h"
#include "qlayoutitem.h"
#include "qdesktopwidget.h"
#include "qevent.h"
#include "qframe.h"
#include "qlabel.h"
#include "qlineedit.h"
#include "qpainter.h"
#include "qpushbutton.h"
#include "qset.h"
#include "qstyle.h"
#include "qvarlengtharray.h"
#if defined(Q_WS_MAC)
#include "private/qt_mac_p.h"
#include "qlibrary.h"
#elif !defined(QT_NO_STYLE_WINDOWSVISTA)
#include "qwizard_win_p.h"
#include "qtimer.h"
#endif

#include "private/qdialog_p.h"
#include <qdebug.h>

#ifdef Q_WS_WINCE
extern bool qt_wince_is_mobile();     //defined in qguifunctions_wce.cpp
#endif

#include <string.h>     // for memset()

#ifdef QT_SOFTKEYS_ENABLED
#include "qaction.h"
#endif

QT_BEGIN_NAMESPACE

// These fudge terms were needed a few places to obtain pixel-perfect results
const int GapBetweenLogoAndRightEdge = 5;
const int ModernHeaderTopMargin = 2;
const int ClassicHMargin = 4;
const int MacButtonTopMargin = 13;
const int MacLayoutLeftMargin = 20;
//const int MacLayoutTopMargin = 14; // Unused. Save some space and avoid warning.
const int MacLayoutRightMargin = 20;
const int MacLayoutBottomMargin = 17;

static void changeSpacerSize(QLayout *layout, int index, int width, int height)
{
    QSpacerItem *spacer = layout->itemAt(index)->spacerItem();
    if (!spacer)
        return;
    spacer->changeSize(width, height);
}

static QWidget *iWantTheFocus(QWidget *ancestor)
{
    const int MaxIterations = 100;

    QWidget *candidate = ancestor;
    for (int i = 0; i < MaxIterations; ++i) {
        candidate = candidate->nextInFocusChain();
        if (!candidate)
            break;

        if (candidate->focusPolicy() & Qt::TabFocus) {
            if (candidate != ancestor && ancestor->isAncestorOf(candidate))
                return candidate;
        }
    }
    return 0;
}

static bool objectInheritsXAndXIsCloserThanY(const QObject *object, const QByteArray &classX,
                                             const QByteArray &classY)
{
    const QMetaObject *metaObject = object->metaObject();
    while (metaObject) {
        if (metaObject->className() == classX)
            return true;
        if (metaObject->className() == classY)
            return false;
        metaObject = metaObject->superClass();
    }
    return false;
}

const int NFallbackDefaultProperties = 7;

const struct {
    const char *className;
    const char *property;
    const char *changedSignal;
} fallbackProperties[NFallbackDefaultProperties] = {
    // If you modify this list, make sure to update the documentation (and the auto test)
    { "QAbstractButton", "checked", SIGNAL(toggled(bool)) },
    { "QAbstractSlider", "value", SIGNAL(valueChanged(int)) },
    { "QComboBox", "currentIndex", SIGNAL(currentIndexChanged(int)) },
    { "QDateTimeEdit", "dateTime", SIGNAL(dateTimeChanged(QDateTime)) },
    { "QLineEdit", "text", SIGNAL(textChanged(QString)) },
    { "QListWidget", "currentRow", SIGNAL(currentRowChanged(int)) },
    { "QSpinBox", "value", SIGNAL(valueChanged(int)) }
};

class QWizardDefaultProperty
{
public:
    QByteArray className;
    QByteArray property;
    QByteArray changedSignal;

    inline QWizardDefaultProperty() {}
    inline QWizardDefaultProperty(const char *className, const char *property,
                                   const char *changedSignal)
        : className(className), property(property), changedSignal(changedSignal) {}
};

class QWizardField
{
public:
    inline QWizardField() {}
    QWizardField(QWizardPage *page, const QString &spec, QObject *object, const char *property,
                  const char *changedSignal);

    void resolve(const QVector<QWizardDefaultProperty> &defaultPropertyTable);
    void findProperty(const QWizardDefaultProperty *properties, int propertyCount);

    QWizardPage *page;
    QString name;
    bool mandatory;
    QObject *object;
    QByteArray property;
    QByteArray changedSignal;
    QVariant initialValue;
};

QWizardField::QWizardField(QWizardPage *page, const QString &spec, QObject *object,
                           const char *property, const char *changedSignal)
    : page(page), name(spec), mandatory(false), object(object), property(property),
      changedSignal(changedSignal)
{
    if (name.endsWith(QLatin1Char('*'))) {
        name.chop(1);
        mandatory = true;
    }
}

void QWizardField::resolve(const QVector<QWizardDefaultProperty> &defaultPropertyTable)
{
    if (property.isEmpty())
        findProperty(defaultPropertyTable.constData(), defaultPropertyTable.count());
    initialValue = object->property(property);
}

void QWizardField::findProperty(const QWizardDefaultProperty *properties, int propertyCount)
{
    QByteArray className;

    for (int i = 0; i < propertyCount; ++i) {
        if (objectInheritsXAndXIsCloserThanY(object, properties[i].className, className)) {
            className = properties[i].className;
            property = properties[i].property;
            changedSignal = properties[i].changedSignal;
        }
    }
}

class QWizardLayoutInfo
{
public:
    inline QWizardLayoutInfo()
    : topLevelMarginLeft(-1), topLevelMarginRight(-1), topLevelMarginTop(-1),
      topLevelMarginBottom(-1), childMarginLeft(-1), childMarginRight(-1),
      childMarginTop(-1), childMarginBottom(-1), hspacing(-1), vspacing(-1),
          wizStyle(QWizard::ClassicStyle), header(false), watermark(false), title(false),
          subTitle(false), extension(false) {}

    int topLevelMarginLeft;
    int topLevelMarginRight;
    int topLevelMarginTop;
    int topLevelMarginBottom;
    int childMarginLeft;
    int childMarginRight;
    int childMarginTop;
    int childMarginBottom;
    int hspacing;
    int vspacing;
    int buttonSpacing;
    QWizard::WizardStyle wizStyle;
    bool header;
    bool watermark;
    bool title;
    bool subTitle;
    bool extension;

    bool operator==(const QWizardLayoutInfo &other);
    inline bool operator!=(const QWizardLayoutInfo &other) { return !operator==(other); }
};

bool QWizardLayoutInfo::operator==(const QWizardLayoutInfo &other)
{
    return topLevelMarginLeft == other.topLevelMarginLeft
           && topLevelMarginRight == other.topLevelMarginRight
           && topLevelMarginTop == other.topLevelMarginTop
           && topLevelMarginBottom == other.topLevelMarginBottom
           && childMarginLeft == other.childMarginLeft
           && childMarginRight == other.childMarginRight
           && childMarginTop == other.childMarginTop
           && childMarginBottom == other.childMarginBottom
           && hspacing == other.hspacing
           && vspacing == other.vspacing
           && buttonSpacing == other.buttonSpacing
           && wizStyle == other.wizStyle
           && header == other.header
           && watermark == other.watermark
           && title == other.title
           && subTitle == other.subTitle
           && extension == other.extension;
}

class QWizardHeader : public QWidget
{
public:
    enum RulerType { Ruler };

    inline QWizardHeader(RulerType /* ruler */, QWidget *parent = 0)
        : QWidget(parent) { setFixedHeight(2); }
    QWizardHeader(QWidget *parent = 0);

    void setup(const QWizardLayoutInfo &info, const QString &title,
               const QString &subTitle, const QPixmap &logo, const QPixmap &banner,
               Qt::TextFormat titleFormat, Qt::TextFormat subTitleFormat);

protected:
    void paintEvent(QPaintEvent *event);
#if !defined(QT_NO_STYLE_WINDOWSVISTA)
private:
    bool vistaDisabled() const;
#endif
private:
    QLabel *titleLabel;
    QLabel *subTitleLabel;
    QLabel *logoLabel;
    QGridLayout *layout;
    QPixmap bannerPixmap;
};

QWizardHeader::QWizardHeader(QWidget *parent)
    : QWidget(parent)
{
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    setBackgroundRole(QPalette::Base);

    titleLabel = new QLabel(this);
    titleLabel->setBackgroundRole(QPalette::Base);

    subTitleLabel = new QLabel(this);
    subTitleLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
    subTitleLabel->setWordWrap(true);

    logoLabel = new QLabel(this);

    QFont font = titleLabel->font();
    font.setBold(true);
    titleLabel->setFont(font);

    layout = new QGridLayout(this);
    layout->setMargin(0);
    layout->setSpacing(0);

    layout->setRowMinimumHeight(3, 1);
    layout->setRowStretch(4, 1);

    layout->setColumnStretch(2, 1);
    layout->setColumnMinimumWidth(4, 2 * GapBetweenLogoAndRightEdge);
    layout->setColumnMinimumWidth(6, GapBetweenLogoAndRightEdge);

    layout->addWidget(titleLabel, 2, 1, 1, 2);
    layout->addWidget(subTitleLabel, 4, 2);
    layout->addWidget(logoLabel, 1, 5, 5, 1);
}

#if !defined(QT_NO_STYLE_WINDOWSVISTA)
bool QWizardHeader::vistaDisabled() const
{
    bool styleDisabled = false;
    QWizard *wiz = parentWidget() ? qobject_cast <QWizard *>(parentWidget()->parentWidget()) : 0;
    if (wiz) {
        // Designer dosen't support the Vista style for Wizards. This property is used to turn
        // off the Vista style.
        const QVariant v = wiz->property("_q_wizard_vista_off");
        styleDisabled = v.isValid() && v.toBool();
    }
    return styleDisabled;
}
#endif

void QWizardHeader::setup(const QWizardLayoutInfo &info, const QString &title,
                          const QString &subTitle, const QPixmap &logo, const QPixmap &banner,
                          Qt::TextFormat titleFormat, Qt::TextFormat subTitleFormat)
{
    bool modern = ((info.wizStyle == QWizard::ModernStyle)
#if !defined(QT_NO_STYLE_WINDOWSVISTA)
        || ((info.wizStyle == QWizard::AeroStyle
            && QVistaHelper::vistaState() == QVistaHelper::Classic) || vistaDisabled())
#endif
    );

    layout->setRowMinimumHeight(0, modern ? ModernHeaderTopMargin : 0);
    layout->setRowMinimumHeight(1, modern ? info.topLevelMarginTop - ModernHeaderTopMargin - 1 : 0);
    layout->setRowMinimumHeight(6, (modern ? 3 : GapBetweenLogoAndRightEdge) + 2);

    int minColumnWidth0 = modern ? info.topLevelMarginLeft + info.topLevelMarginRight : 0;
    int minColumnWidth1 = modern ? info.topLevelMarginLeft + info.topLevelMarginRight + 1
                                 : info.topLevelMarginLeft + ClassicHMargin;
    layout->setColumnMinimumWidth(0, minColumnWidth0);
    layout->setColumnMinimumWidth(1, minColumnWidth1);

    titleLabel->setTextFormat(titleFormat);
    titleLabel->setText(title);
    logoLabel->setPixmap(logo);

    subTitleLabel->setTextFormat(subTitleFormat);
    subTitleLabel->setText(QLatin1String("Pq\nPq"));
    int desiredSubTitleHeight = subTitleLabel->sizeHint().height();
    subTitleLabel->setText(subTitle);

    if (modern) {
        bannerPixmap = banner;
    } else {
        bannerPixmap = QPixmap();
    }

    if (bannerPixmap.isNull()) {
        /*
            There is no widthForHeight() function, so we simulate it with a loop.
        */
        int candidateSubTitleWidth = qMin(512, 2 * QApplication::desktop()->width() / 3);
        int delta = candidateSubTitleWidth >> 1;
        while (delta > 0) {
            if (subTitleLabel->heightForWidth(candidateSubTitleWidth - delta)
                        <= desiredSubTitleHeight)
                candidateSubTitleWidth -= delta;
            delta >>= 1;
        }

        subTitleLabel->setMinimumSize(candidateSubTitleWidth, desiredSubTitleHeight);

        QSize size = layout->totalMinimumSize();
        setMinimumSize(size);
        setMaximumSize(QWIDGETSIZE_MAX, size.height());
    } else {
        subTitleLabel->setMinimumSize(0, 0);
        setFixedSize(banner.size() + QSize(0, 2));
    }
    updateGeometry();
}

void QWizardHeader::paintEvent(QPaintEvent * /* event */)
{
    QPainter painter(this);
    painter.drawPixmap(0, 0, bannerPixmap);

    int x = width() - 2;
    int y = height() - 2;
    const QPalette &pal = palette();
    painter.setPen(pal.mid().color());
    painter.drawLine(0, y, x, y);
    painter.setPen(pal.base().color());
    painter.drawPoint(x + 1, y);
    painter.drawLine(0, y + 1, x + 1, y + 1);
}

// We save one vtable by basing QWizardRuler on QWizardHeader
class QWizardRuler : public QWizardHeader
{
public:
    inline QWizardRuler(QWidget *parent = 0)
        : QWizardHeader(Ruler, parent) {}
};

class QWizardPagePrivate : public QWidgetPrivate
{
    Q_DECLARE_PUBLIC(QWizardPage)

public:
    enum TriState { Tri_Unknown = -1, Tri_False, Tri_True };

    inline QWizardPagePrivate()
        : wizard(0), completeState(Tri_Unknown), explicitlyFinal(false), commit(false) {}

    bool cachedIsComplete() const;
    void _q_maybeEmitCompleteChanged();
    void _q_updateCachedCompleteState();

    QWizard *wizard;
    QString title;
    QString subTitle;
    QPixmap pixmaps[QWizard::NPixmaps];
    QVector<QWizardField> pendingFields;
    mutable TriState completeState;
    bool explicitlyFinal;
    bool commit;
    QMap<int, QString> buttonCustomTexts;
};

bool QWizardPagePrivate::cachedIsComplete() const
{
    Q_Q(const QWizardPage);
    if (completeState == Tri_Unknown)
        completeState = q->isComplete() ? Tri_True : Tri_False;
    return completeState == Tri_True;
}

void QWizardPagePrivate::_q_maybeEmitCompleteChanged()
{
    Q_Q(QWizardPage);
    TriState newState = q->isComplete() ? Tri_True : Tri_False;
    if (newState != completeState)
        emit q->completeChanged();
}

void QWizardPagePrivate::_q_updateCachedCompleteState()
{
    Q_Q(QWizardPage);
    completeState = q->isComplete() ? Tri_True : Tri_False;
}

class QWizardAntiFlickerWidget : public QWidget
{
    QWizard *wizard;
    QWizardPrivate *wizardPrivate;
public:
    QWizardAntiFlickerWidget(QWizard *wizard, QWizardPrivate *wizardPrivate)
        : QWidget(wizard)
        , wizard(wizard)
        , wizardPrivate(wizardPrivate) {}
#if !defined(QT_NO_STYLE_WINDOWSVISTA)
protected:
    void paintEvent(QPaintEvent *);
#endif
};

class QWizardPrivate : public QDialogPrivate
{
    Q_DECLARE_PUBLIC(QWizard)

public:
    typedef QMap<int, QWizardPage *> PageMap;

    enum Direction {
        Backward,
        Forward
    };

    inline QWizardPrivate()
        : start(-1)
        , current(-1)
        , canContinue(false)
        , canFinish(false)
        , disableUpdatesCount(0)
        , opts(0)
        , buttonsHaveCustomLayout(false)
        , titleFmt(Qt::AutoText)
        , subTitleFmt(Qt::AutoText)
        , placeholderWidget1(0)
        , placeholderWidget2(0)
        , headerWidget(0)
        , watermarkLabel(0)
        , titleLabel(0)
        , subTitleLabel(0)
        , bottomRuler(0)
#if !defined(QT_NO_STYLE_WINDOWSVISTA)
        , vistaInitPending(false)
        , vistaState(QVistaHelper::Dirty)
        , vistaStateChanged(false)
        , inHandleAeroStyleChange(false)
#endif
        , minimumWidth(0)
        , minimumHeight(0)
        , maximumWidth(QWIDGETSIZE_MAX)
        , maximumHeight(QWIDGETSIZE_MAX)
    {
        for (int i = 0; i < QWizard::NButtons; ++i) {
            btns[i] = 0;
#ifdef QT_SOFTKEYS_ENABLED
            softKeys[i] = 0;
#endif
        }
#if !defined(QT_NO_STYLE_WINDOWSVISTA)
        if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA
            && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)
            vistaInitPending = true;
#endif
    }

    void init();
    void reset();
    void cleanupPagesNotInHistory();
    void addField(const QWizardField &field);
    void removeFieldAt(int index);
    void switchToPage(int newId, Direction direction);
    QWizardLayoutInfo layoutInfoForCurrentPage();
    void recreateLayout(const QWizardLayoutInfo &info);
    void updateLayout();
    void updateMinMaxSizes(const QWizardLayoutInfo &info);
    void updateCurrentPage();
    bool ensureButton(QWizard::WizardButton which) const;
    void connectButton(QWizard::WizardButton which) const;
    void updateButtonTexts();
    void updateButtonLayout();
    void setButtonLayout(const QWizard::WizardButton *array, int size);
    bool buttonLayoutContains(QWizard::WizardButton which);
    void updatePixmap(QWizard::WizardPixmap which);
#if !defined(QT_NO_STYLE_WINDOWSVISTA)
    bool vistaDisabled() const;
    bool isVistaThemeEnabled(QVistaHelper::VistaState state) const;
    void handleAeroStyleChange();
#endif
    bool isVistaThemeEnabled() const;
    void disableUpdates();
    void enableUpdates();
    void _q_emitCustomButtonClicked();
    void _q_updateButtonStates();
    void _q_handleFieldObjectDestroyed(QObject *);
    void setStyle(QStyle *style);
#ifdef Q_WS_MAC
    static QPixmap findDefaultBackgroundPixmap();
#endif

    PageMap pageMap;
    QVector<QWizardField> fields;
    QMap<QString, int> fieldIndexMap;
    QVector<QWizardDefaultProperty> defaultPropertyTable;
    QList<int> history;
    QSet<int> initialized; // ### remove and move bit to QWizardPage?
    int start;
    int current;
    bool canContinue;
    bool canFinish;
    QWizardLayoutInfo layoutInfo;
    int disableUpdatesCount;

    QWizard::WizardStyle wizStyle;
    QWizard::WizardOptions opts;
    QMap<int, QString> buttonCustomTexts;
    bool buttonsHaveCustomLayout;
    QList<QWizard::WizardButton> buttonsCustomLayout;
    Qt::TextFormat titleFmt;
    Qt::TextFormat subTitleFmt;
    mutable QPixmap defaultPixmaps[QWizard::NPixmaps];

    union {
        // keep in sync with QWizard::WizardButton
        mutable struct {
            QAbstractButton *back;
            QAbstractButton *next;
            QAbstractButton *commit;
            QAbstractButton *finish;
            QAbstractButton *cancel;
            QAbstractButton *help;
        } btn;
        mutable QAbstractButton *btns[QWizard::NButtons];
    };
    QWizardAntiFlickerWidget *antiFlickerWidget;
    QWidget *placeholderWidget1;
    QWidget *placeholderWidget2;
    QWizardHeader *headerWidget;
    QLabel *watermarkLabel;
    QFrame *pageFrame;
    QLabel *titleLabel;
    QLabel *subTitleLabel;
    QWizardRuler *bottomRuler;
#ifdef QT_SOFTKEYS_ENABLED
    mutable QAction *softKeys[QWizard::NButtons];
#endif

    QVBoxLayout *pageVBoxLayout;
    QHBoxLayout *buttonLayout;
    QGridLayout *mainLayout;

#if !defined(QT_NO_STYLE_WINDOWSVISTA)
    QVistaHelper *vistaHelper;
    bool vistaInitPending;
    QVistaHelper::VistaState vistaState;
    bool vistaStateChanged;
    bool inHandleAeroStyleChange;
#endif
    int minimumWidth;
    int minimumHeight;
    int maximumWidth;
    int maximumHeight;
};

static QString buttonDefaultText(int wstyle, int which, const QWizardPrivate *wizardPrivate)
{
#if defined(QT_NO_STYLE_WINDOWSVISTA)
    Q_UNUSED(wizardPrivate);
#endif
    const bool macStyle = (wstyle == QWizard::MacStyle);
    switch (which) {
    case QWizard::BackButton:
        return macStyle ? QWizard::tr("Go Back") : QWizard::tr("< &Back");
    case QWizard::NextButton:
        if (macStyle)
            return QWizard::tr("Continue");
        else
            return wizardPrivate->isVistaThemeEnabled()
                ? QWizard::tr("&Next") : QWizard::tr("&Next >");
    case QWizard::CommitButton:
        return QWizard::tr("Commit");
    case QWizard::FinishButton:
        return macStyle ? QWizard::tr("Done") : QWizard::tr("&Finish");
    case QWizard::CancelButton:
        return QWizard::tr("Cancel");
    case QWizard::HelpButton:
        return macStyle ? QWizard::tr("Help") : QWizard::tr("&Help");
    default:
        return QString();
    }
}

void QWizardPrivate::init()
{
    Q_Q(QWizard);

    antiFlickerWidget = new QWizardAntiFlickerWidget(q, this);
    wizStyle = QWizard::WizardStyle(q->style()->styleHint(QStyle::SH_WizardStyle, 0, q));
    if (wizStyle == QWizard::MacStyle) {
        opts = (QWizard::NoDefaultButton | QWizard::NoCancelButton);
    } else if (wizStyle == QWizard::ModernStyle) {
        opts = QWizard::HelpButtonOnRight;
    }

#if !defined(QT_NO_STYLE_WINDOWSVISTA)
    vistaHelper = new QVistaHelper(q);
#endif

    // create these buttons right away; create the other buttons as necessary
    ensureButton(QWizard::BackButton);
    ensureButton(QWizard::NextButton);
    ensureButton(QWizard::CommitButton);
    ensureButton(QWizard::FinishButton);

    pageFrame = new QFrame(antiFlickerWidget);
    pageFrame->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);

    pageVBoxLayout = new QVBoxLayout(pageFrame);
    pageVBoxLayout->setSpacing(0);
    pageVBoxLayout->addSpacing(0);
    QSpacerItem *spacerItem = new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding);
    pageVBoxLayout->addItem(spacerItem);

    buttonLayout = new QHBoxLayout;
    mainLayout = new QGridLayout(antiFlickerWidget);
    mainLayout->setSizeConstraint(QLayout::SetNoConstraint);

    updateButtonLayout();

    for (int i = 0; i < NFallbackDefaultProperties; ++i)
        defaultPropertyTable.append(QWizardDefaultProperty(fallbackProperties[i].className,
                                                           fallbackProperties[i].property,
                                                           fallbackProperties[i].changedSignal));
}

void QWizardPrivate::reset()
{
    Q_Q(QWizard);
    if (current != -1) {
        q->currentPage()->hide();
        cleanupPagesNotInHistory();
        for (int i = history.count() - 1; i >= 0; --i)
            q->cleanupPage(history.at(i));
        history.clear();
        initialized.clear();

        current = -1;
        emit q->currentIdChanged(-1);
    }
}

void QWizardPrivate::cleanupPagesNotInHistory()
{
    Q_Q(QWizard);

    const QSet<int> original = initialized;
    QSet<int>::const_iterator i = original.constBegin();
    QSet<int>::const_iterator end = original.constEnd();

    for (; i != end; ++i) {
        if (!history.contains(*i)) {
            q->cleanupPage(*i);
            initialized.remove(*i);
        }
    }
}

void QWizardPrivate::addField(const QWizardField &field)
{
    Q_Q(QWizard);

    QWizardField myField = field;
    myField.resolve(defaultPropertyTable);

    if (fieldIndexMap.contains(myField.name)) {
        qWarning("QWizardPage::addField: Duplicate field '%s'", qPrintable(myField.name));
        return;
    }

    fieldIndexMap.insert(myField.name, fields.count());
    fields += myField;
    if (myField.mandatory && !myField.changedSignal.isEmpty())
        QObject::connect(myField.object, myField.changedSignal,
                         myField.page, SLOT(_q_maybeEmitCompleteChanged()));
    QObject::connect(
        myField.object, SIGNAL(destroyed(QObject *)), q,
        SLOT(_q_handleFieldObjectDestroyed(QObject *)));
}

void QWizardPrivate::removeFieldAt(int index)
{
    Q_Q(QWizard);

    const QWizardField &field = fields.at(index);
    fieldIndexMap.remove(field.name);
    if (field.mandatory && !field.changedSignal.isEmpty())
        QObject::disconnect(field.object, field.changedSignal,
                            field.page, SLOT(_q_maybeEmitCompleteChanged()));
    QObject::disconnect(
        field.object, SIGNAL(destroyed(QObject *)), q,
        SLOT(_q_handleFieldObjectDestroyed(QObject *)));
    fields.remove(index);
}

void QWizardPrivate::switchToPage(int newId, Direction direction)
{
    Q_Q(QWizard);

    disableUpdates();

    int oldId = current;
    if (QWizardPage *oldPage = q->currentPage()) {
        oldPage->hide();

        if (direction == Backward) {
            if (!(opts & QWizard::IndependentPages)) {
                q->cleanupPage(oldId);
                initialized.remove(oldId);
            }
            Q_ASSERT(history.last() == oldId);
            history.removeLast();
            Q_ASSERT(history.last() == newId);
        }
    }

    current = newId;

    QWizardPage *newPage = q->currentPage();
    if (newPage) {
        if (direction == Forward) {
            if (!initialized.contains(current)) {
                initialized.insert(current);
                q->initializePage(current);
            }
            history.append(current);
        }
        newPage->show();
    }

    canContinue = (q->nextId() != -1);
    canFinish = (newPage && newPage->isFinalPage());

    _q_updateButtonStates();
    updateButtonTexts();

    const QWizard::WizardButton nextOrCommit =
        newPage && newPage->isCommitPage() ? QWizard::CommitButton : QWizard::NextButton;
    QAbstractButton *nextOrFinishButton =
        btns[canContinue ? nextOrCommit : QWizard::FinishButton];
    QWidget *candidate = 0;

    /*
        If there is no default button and the Next or Finish button
        is enabled, give focus directly to it as a convenience to the
        user. This is the normal case on Mac OS X.

        Otherwise, give the focus to the new page's first child that
        can handle it. If there is no such child, give the focus to
        Next or Finish.
    */
    if ((opts & QWizard::NoDefaultButton) && nextOrFinishButton->isEnabled()) {
        candidate = nextOrFinishButton;
    } else if (newPage) {
        candidate = iWantTheFocus(newPage);
    }
    if (!candidate)
        candidate = nextOrFinishButton;
    candidate->setFocus();

    if (wizStyle == QWizard::MacStyle)
        q->updateGeometry();

    enableUpdates();
    updateLayout();

    emit q->currentIdChanged(current);
}

// keep in sync with QWizard::WizardButton
static const char * const buttonSlots[QWizard::NStandardButtons] = {
    SLOT(back()), SLOT(next()), SLOT(next()), SLOT(accept()), SLOT(reject()),
    SIGNAL(helpRequested())
};

QWizardLayoutInfo QWizardPrivate::layoutInfoForCurrentPage()
{
    Q_Q(QWizard);
    QStyle *style = q->style();

    QWizardLayoutInfo info;

    const int layoutHorizontalSpacing = style->pixelMetric(QStyle::PM_LayoutHorizontalSpacing);
    info.topLevelMarginLeft = style->pixelMetric(QStyle::PM_LayoutLeftMargin, 0, q);
    info.topLevelMarginRight = style->pixelMetric(QStyle::PM_LayoutRightMargin, 0, q);
    info.topLevelMarginTop = style->pixelMetric(QStyle::PM_LayoutTopMargin, 0, q);
    info.topLevelMarginBottom = style->pixelMetric(QStyle::PM_LayoutBottomMargin, 0, q);
    info.childMarginLeft = style->pixelMetric(QStyle::PM_LayoutLeftMargin, 0, titleLabel);
    info.childMarginRight = style->pixelMetric(QStyle::PM_LayoutRightMargin, 0, titleLabel);
    info.childMarginTop = style->pixelMetric(QStyle::PM_LayoutTopMargin, 0, titleLabel);
    info.childMarginBottom = style->pixelMetric(QStyle::PM_LayoutBottomMargin, 0, titleLabel);
    info.hspacing = (layoutHorizontalSpacing == -1)
        ? style->layoutSpacing(QSizePolicy::DefaultType, QSizePolicy::DefaultType, Qt::Horizontal)
        : layoutHorizontalSpacing;
    info.vspacing = style->pixelMetric(QStyle::PM_LayoutVerticalSpacing);
    info.buttonSpacing = (layoutHorizontalSpacing == -1)
        ? style->layoutSpacing(QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal)
        : layoutHorizontalSpacing;

    if (wizStyle == QWizard::MacStyle)
        info.buttonSpacing = 12;

    info.wizStyle = wizStyle;
    if ((info.wizStyle == QWizard::AeroStyle)
#if !defined(QT_NO_STYLE_WINDOWSVISTA)
        && (QVistaHelper::vistaState() == QVistaHelper::Classic || vistaDisabled())
#endif
        )
        info.wizStyle = QWizard::ModernStyle;

    QString titleText;
    QString subTitleText;
    QPixmap backgroundPixmap;
    QPixmap watermarkPixmap;

    if (QWizardPage *page = q->currentPage()) {
        titleText = page->title();
        subTitleText = page->subTitle();
        backgroundPixmap = page->pixmap(QWizard::BackgroundPixmap);
        watermarkPixmap = page->pixmap(QWizard::WatermarkPixmap);
    }

    info.header = (info.wizStyle == QWizard::ClassicStyle || info.wizStyle == QWizard::ModernStyle)
        && !(opts & QWizard::IgnoreSubTitles) && !subTitleText.isEmpty();
    info.watermark = (info.wizStyle != QWizard::MacStyle) && (info.wizStyle != QWizard::AeroStyle)
        && !watermarkPixmap.isNull();
    info.title = !info.header && !titleText.isEmpty();
    info.subTitle = !(opts & QWizard::IgnoreSubTitles) && !info.header && !subTitleText.isEmpty();
    info.extension = info.watermark && (opts & QWizard::ExtendedWatermarkPixmap);

    return info;
}

void QWizardPrivate::recreateLayout(const QWizardLayoutInfo &info)
{
    Q_Q(QWizard);

    /*
        Start by undoing the main layout.
    */
    for (int i = mainLayout->count() - 1; i >= 0; --i) {
        QLayoutItem *item = mainLayout->takeAt(i);
        if (item->layout()) {
            item->layout()->setParent(0);
        } else {
            delete item;
        }
    }
    for (int i = mainLayout->columnCount() - 1; i >= 0; --i)
        mainLayout->setColumnMinimumWidth(i, 0);
    for (int i = mainLayout->rowCount() - 1; i >= 0; --i)
        mainLayout->setRowMinimumHeight(i, 0);

    /*
        Now, recreate it.
    */

    bool mac = (info.wizStyle == QWizard::MacStyle);
    bool classic = (info.wizStyle == QWizard::ClassicStyle);
    bool modern = (info.wizStyle == QWizard::ModernStyle);
    bool aero = (info.wizStyle == QWizard::AeroStyle);
    int deltaMarginLeft = info.topLevelMarginLeft - info.childMarginLeft;
    int deltaMarginRight = info.topLevelMarginRight - info.childMarginRight;
    int deltaMarginTop = info.topLevelMarginTop - info.childMarginTop;
    int deltaMarginBottom = info.topLevelMarginBottom - info.childMarginBottom;
    int deltaVSpacing = info.topLevelMarginBottom - info.vspacing;

    int row = 0;
    int numColumns;
    if (mac) {
        numColumns = 3;
    } else if (info.watermark) {
        numColumns = 2;
    } else {
        numColumns = 1;
    }
    int pageColumn = qMin(1, numColumns - 1);

    if (mac) {
        mainLayout->setMargin(0);
        mainLayout->setSpacing(0);
        buttonLayout->setContentsMargins(MacLayoutLeftMargin, MacButtonTopMargin, MacLayoutRightMargin, MacLayoutBottomMargin);
        pageVBoxLayout->setMargin(7);
    } else {
        if (modern) {
            mainLayout->setMargin(0);
            mainLayout->setSpacing(0);
            pageVBoxLayout->setContentsMargins(deltaMarginLeft, deltaMarginTop,
                                               deltaMarginRight, deltaMarginBottom);
            buttonLayout->setContentsMargins(info.topLevelMarginLeft, info.topLevelMarginTop,
                                             info.topLevelMarginRight, info.topLevelMarginBottom);
        } else {
            mainLayout->setContentsMargins(info.topLevelMarginLeft, info.topLevelMarginTop,
                                           info.topLevelMarginRight, info.topLevelMarginBottom);
            mainLayout->setHorizontalSpacing(info.hspacing);
            mainLayout->setVerticalSpacing(info.vspacing);
            pageVBoxLayout->setContentsMargins(0, 0, 0, 0);
            buttonLayout->setContentsMargins(0, 0, 0, 0);
        }
    }
    buttonLayout->setSpacing(info.buttonSpacing);

    if (info.header) {
        if (!headerWidget)
            headerWidget = new QWizardHeader(antiFlickerWidget);
        headerWidget->setAutoFillBackground(modern);
        mainLayout->addWidget(headerWidget, row++, 0, 1, numColumns);
    }
    if (headerWidget)
        headerWidget->setVisible(info.header);

    int watermarkStartRow = row;

    if (mac)
        mainLayout->setRowMinimumHeight(row++, 10);

    if (info.title) {
        if (!titleLabel) {
            titleLabel = new QLabel(antiFlickerWidget);
            titleLabel->setBackgroundRole(QPalette::Base);
            titleLabel->setWordWrap(true);
        }

        QFont titleFont = q->font();
        titleFont.setPointSize(titleFont.pointSize() + (mac ? 3 : 4));
        titleFont.setBold(true);
        titleLabel->setPalette(QPalette());

        if (aero) {
            // ### hardcoded for now:
            titleFont = QFont(QLatin1String("Segoe UI"), 12);
            QPalette pal(titleLabel->palette());
            pal.setColor(QPalette::Text, "#003399");
            titleLabel->setPalette(pal);
        }

        titleLabel->setFont(titleFont);
        const int aeroTitleIndent = 25; // ### hardcoded for now - should be calculated somehow
        if (aero)
            titleLabel->setIndent(aeroTitleIndent);
        else if (mac)
            titleLabel->setIndent(2);
        else if (classic)
            titleLabel->setIndent(info.childMarginLeft);
        else
            titleLabel->setIndent(info.topLevelMarginLeft);
        if (modern) {
            if (!placeholderWidget1) {
                placeholderWidget1 = new QWidget(antiFlickerWidget);
                placeholderWidget1->setBackgroundRole(QPalette::Base);
            }
            placeholderWidget1->setFixedHeight(info.topLevelMarginLeft + 2);
            mainLayout->addWidget(placeholderWidget1, row++, pageColumn);
        }
        mainLayout->addWidget(titleLabel, row++, pageColumn);
        if (modern) {
            if (!placeholderWidget2) {
                placeholderWidget2 = new QWidget(antiFlickerWidget);
                placeholderWidget2->setBackgroundRole(QPalette::Base);
            }
            placeholderWidget2->setFixedHeight(5);
            mainLayout->addWidget(placeholderWidget2, row++, pageColumn);
        }
        if (mac)
            mainLayout->setRowMinimumHeight(row++, 7);
    }
    if (placeholderWidget1)
        placeholderWidget1->setVisible(info.title && modern);
    if (placeholderWidget2)
        placeholderWidget2->setVisible(info.title && modern);

    if (info.subTitle) {
        if (!subTitleLabel) {
            subTitleLabel = new QLabel(pageFrame);
            subTitleLabel->setWordWrap(true);

            subTitleLabel->setContentsMargins(info.childMarginLeft , 0,
                                              info.childMarginRight , 0);

            pageVBoxLayout->insertWidget(1, subTitleLabel);
        }
    }

    // ### try to replace with margin.
    changeSpacerSize(pageVBoxLayout, 0, 0, info.subTitle ? info.childMarginLeft : 0);

    int hMargin = mac ? 1 : 0;
    int vMargin = hMargin;

    pageFrame->setFrameStyle(mac ? (QFrame::Box | QFrame::Raised) : QFrame::NoFrame);
    pageFrame->setLineWidth(0);
    pageFrame->setMidLineWidth(hMargin);

    if (info.header) {
        if (modern) {
            hMargin = info.topLevelMarginLeft;
            vMargin = deltaMarginBottom;
        } else if (classic) {
            hMargin = deltaMarginLeft + ClassicHMargin;
            vMargin = 0;
        }
    }

    if (aero) {
        int leftMargin   = 18; // ### hardcoded for now - should be calculated somehow
        int topMargin    = vMargin;
        int rightMargin  = hMargin; // ### for now
        int bottomMargin = vMargin;
        pageFrame->setContentsMargins(leftMargin, topMargin, rightMargin, bottomMargin);
    } else {
        pageFrame->setContentsMargins(hMargin, vMargin, hMargin, vMargin);
    }

    if (info.watermark && !watermarkLabel) {
        watermarkLabel = new QLabel(antiFlickerWidget);
        watermarkLabel->setBackgroundRole(QPalette::Base);
        watermarkLabel->setMinimumHeight(1);
        watermarkLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
        watermarkLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop);
    }

    //bool wasSemiTransparent = pageFrame->testAttribute(Qt::WA_SetPalette);
    const bool wasSemiTransparent =
        pageFrame->palette().brush(QPalette::Window).color().alpha() < 255
        || pageFrame->palette().brush(QPalette::Base).color().alpha() < 255;
    if (mac) {
        if (!wasSemiTransparent) {
            QPalette pal = pageFrame->palette();
            pal.setBrush(QPalette::Window, QColor(255, 255, 255, 153));
            // ### The next line is required to ensure visual semitransparency when
            // ### switching from ModernStyle to MacStyle. See TAG1 below.
            pal.setBrush(QPalette::Base, QColor(255, 255, 255, 153));
            pageFrame->setPalette(pal);
            pageFrame->setAutoFillBackground(true);
            antiFlickerWidget->setAutoFillBackground(false);
        }
    } else {
        if (wasSemiTransparent)
            pageFrame->setPalette(QPalette());

        bool baseBackground = (modern && !info.header); // ### TAG1
        pageFrame->setBackgroundRole(baseBackground ? QPalette::Base : QPalette::Window);

        if (titleLabel)
            titleLabel->setAutoFillBackground(baseBackground);
        pageFrame->setAutoFillBackground(baseBackground);
        if (watermarkLabel)
            watermarkLabel->setAutoFillBackground(baseBackground);
        if (placeholderWidget1)
            placeholderWidget1->setAutoFillBackground(baseBackground);
        if (placeholderWidget2)
            placeholderWidget2->setAutoFillBackground(baseBackground);

        if (aero) {
            QPalette pal = pageFrame->palette();
            pal.setBrush(QPalette::Window, QColor(255, 255, 255));
            pageFrame->setPalette(pal);
            pageFrame->setAutoFillBackground(true);
            pal = antiFlickerWidget->palette();
            pal.setBrush(QPalette::Window, QColor(255, 255, 255));
            antiFlickerWidget->setPalette(pal);
            antiFlickerWidget->setAutoFillBackground(true);
        }
    }

    mainLayout->addWidget(pageFrame, row++, pageColumn);

    int watermarkEndRow = row;
    if (classic)
        mainLayout->setRowMinimumHeight(row++, deltaVSpacing);

    if (aero) {
        buttonLayout->setContentsMargins(9, 9, 9, 9);
        mainLayout->setContentsMargins(0, 11, 0, 0);
    }

    int buttonStartColumn = info.extension ? 1 : 0;
    int buttonNumColumns = info.extension ? 1 : numColumns;

    if (classic || modern) {
        if (!bottomRuler)
            bottomRuler = new QWizardRuler(antiFlickerWidget);
        mainLayout->addWidget(bottomRuler, row++, buttonStartColumn, 1, buttonNumColumns);
    }

    if (classic)
        mainLayout->setRowMinimumHeight(row++, deltaVSpacing);

    mainLayout->addLayout(buttonLayout, row++, buttonStartColumn, 1, buttonNumColumns);

    if (info.watermark) {
        if (info.extension)
            watermarkEndRow = row;
        mainLayout->addWidget(watermarkLabel, watermarkStartRow, 0,
                              watermarkEndRow - watermarkStartRow, 1);
    }

    mainLayout->setColumnMinimumWidth(0, mac && !info.watermark ? 181 : 0);
    if (mac)
        mainLayout->setColumnMinimumWidth(2, 21);

    if (headerWidget)
        headerWidget->setVisible(info.header);
    if (titleLabel)
        titleLabel->setVisible(info.title);
    if (subTitleLabel)
        subTitleLabel->setVisible(info.subTitle);
    if (bottomRuler)
        bottomRuler->setVisible(classic || modern);
    if (watermarkLabel)
        watermarkLabel->setVisible(info.watermark);

    layoutInfo = info;
}

void QWizardPrivate::updateLayout()
{
    Q_Q(QWizard);

    disableUpdates();

    QWizardLayoutInfo info = layoutInfoForCurrentPage();
    if (layoutInfo != info)
        recreateLayout(info);
    QWizardPage *page = q->currentPage();

    // If the page can expand vertically, let it stretch "infinitely" more
    // than the QSpacerItem at the bottom. Otherwise, let the QSpacerItem
    // stretch "infinitely" more than the page. Change the bottom item's
    // policy accordingly. The case that the page has no layout is basically
    // for Designer, only.
    if (page) {
        bool expandPage = !page->layout();
        if (!expandPage) {
            const QLayoutItem *pageItem = pageVBoxLayout->itemAt(pageVBoxLayout->indexOf(page));
            expandPage = pageItem->expandingDirections() & Qt::Vertical;
        }
        QSpacerItem *bottomSpacer = pageVBoxLayout->itemAt(pageVBoxLayout->count() -  1)->spacerItem();
        Q_ASSERT(bottomSpacer);
        bottomSpacer->changeSize(0, 0, QSizePolicy::Ignored, expandPage ? QSizePolicy::Ignored : QSizePolicy::MinimumExpanding);
        pageVBoxLayout->invalidate();
    }

    if (info.header) {
        Q_ASSERT(page);
        headerWidget->setup(info, page->title(), page->subTitle(),
                            page->pixmap(QWizard::LogoPixmap), page->pixmap(QWizard::BannerPixmap),
                            titleFmt, subTitleFmt);
    }

    if (info.watermark) {
        Q_ASSERT(page);
        watermarkLabel->setPixmap(page->pixmap(QWizard::WatermarkPixmap));
    }
    if (info.title) {
        Q_ASSERT(page);
        titleLabel->setTextFormat(titleFmt);
        titleLabel->setText(page->title());
    }
    if (info.subTitle) {
        Q_ASSERT(page);
        subTitleLabel->setTextFormat(subTitleFmt);
        subTitleLabel->setText(page->subTitle());
    }

    enableUpdates();
    updateMinMaxSizes(info);
}

void QWizardPrivate::updateMinMaxSizes(const QWizardLayoutInfo &info)
{
    Q_Q(QWizard);

    int extraHeight = 0;
#if !defined(QT_NO_STYLE_WINDOWSVISTA)
    if (isVistaThemeEnabled())
        extraHeight = vistaHelper->titleBarSize() + vistaHelper->topOffset();
#endif
    QSize minimumSize = mainLayout->totalMinimumSize() + QSize(0, extraHeight);
    QSize maximumSize = mainLayout->totalMaximumSize();
    if (info.header && headerWidget->maximumWidth() != QWIDGETSIZE_MAX) {
        minimumSize.setWidth(headerWidget->maximumWidth());
        maximumSize.setWidth(headerWidget->maximumWidth());
    }
    if (info.watermark) {
        minimumSize.setHeight(mainLayout->totalSizeHint().height());
        maximumSize.setHeight(mainLayout->totalSizeHint().height());
    }
    if (q->minimumWidth() == minimumWidth) {
        minimumWidth = minimumSize.width();
        q->setMinimumWidth(minimumWidth);
    }
    if (q->minimumHeight() == minimumHeight) {
        minimumHeight = minimumSize.height();
        q->setMinimumHeight(minimumHeight);
    }
    if (q->maximumWidth() == maximumWidth) {
        maximumWidth = maximumSize.width();
        q->setMaximumWidth(maximumWidth);
    }
    if (q->maximumHeight() == maximumHeight) {
        maximumHeight = maximumSize.height();
        q->setMaximumHeight(maximumHeight);
    }
}

void QWizardPrivate::updateCurrentPage()
{
    Q_Q(QWizard);
    if (q->currentPage()) {
        canContinue = (q->nextId() != -1);
        canFinish = q->currentPage()->isFinalPage();
    } else {
        canContinue = false;
        canFinish = false;
    }
    _q_updateButtonStates();
    updateButtonTexts();
}

bool QWizardPrivate::ensureButton(QWizard::WizardButton which) const
{
    Q_Q(const QWizard);
    if (uint(which) >= QWizard::NButtons)
        return false;

    if (!btns[which]) {
        QPushButton *pushButton = new QPushButton(antiFlickerWidget);
        QStyle *style = q->style();
        if (style != QApplication::style()) // Propagate style
            pushButton->setStyle(style);
        // Make navigation buttons detectable as passive interactor in designer
        switch (which) {
            case QWizard::CommitButton:
            case QWizard::FinishButton:
            case QWizard::CancelButton:
            break;
        default: {
            QString objectName = QLatin1String("__qt__passive_wizardbutton");
            objectName += QString::number(which);
            pushButton->setObjectName(objectName);
        }
            break;
        }
#ifdef Q_WS_MAC
        pushButton->setAutoDefault(false);
#endif
        pushButton->hide();
#ifdef Q_CC_HPACC
        const_cast<QWizardPrivate *>(this)->btns[which] = pushButton;
#else
        btns[which] = pushButton;
#endif
        if (which < QWizard::NStandardButtons)
            pushButton->setText(buttonDefaultText(wizStyle, which, this));

#ifdef QT_SOFTKEYS_ENABLED
        QAction *softKey = new QAction(pushButton->text(), pushButton);
        QAction::SoftKeyRole softKeyRole;
        switch(which) {
        case QWizard::NextButton:
        case QWizard::FinishButton:
        case QWizard::CancelButton:
            softKeyRole = QAction::NegativeSoftKey;
            break;
        case QWizard::BackButton:
        case QWizard::CommitButton:
        case QWizard::HelpButton:
        case QWizard::CustomButton1:
        case QWizard::CustomButton2:
        case QWizard::CustomButton3:
        default:
            softKeyRole = QAction::PositiveSoftKey;
            break;
        }
        softKey->setSoftKeyRole(softKeyRole);
        softKeys[which] = softKey;
#endif
        connectButton(which);
    }
    return true;
}

void QWizardPrivate::connectButton(QWizard::WizardButton which) const
{
    Q_Q(const QWizard);
    if (which < QWizard::NStandardButtons) {
        QObject::connect(btns[which], SIGNAL(clicked()), q, buttonSlots[which]);
    } else {
        QObject::connect(btns[which], SIGNAL(clicked()), q, SLOT(_q_emitCustomButtonClicked()));
    }

#ifdef QT_SOFTKEYS_ENABLED
    QObject::connect(softKeys[which], SIGNAL(triggered()), btns[which], SIGNAL(clicked()));
#endif
}

void QWizardPrivate::updateButtonTexts()
{
    Q_Q(QWizard);
    for (int i = 0; i < QWizard::NButtons; ++i) {
        if (btns[i]) {
            if (q->currentPage() && (q->currentPage()->d_func()->buttonCustomTexts.contains(i)))
                btns[i]->setText(q->currentPage()->d_func()->buttonCustomTexts.value(i));
            else if (buttonCustomTexts.contains(i))
                btns[i]->setText(buttonCustomTexts.value(i));
            else if (i < QWizard::NStandardButtons)
                btns[i]->setText(buttonDefaultText(wizStyle, i, this));
#ifdef QT_SOFTKEYS_ENABLED
            softKeys[i]->setText(btns[i]->text());
#endif
        }
    }
}

void QWizardPrivate::updateButtonLayout()
{
    if (buttonsHaveCustomLayout) {
        QVarLengthArray<QWizard::WizardButton> array(buttonsCustomLayout.count());
        for (int i = 0; i < buttonsCustomLayout.count(); ++i)
            array[i] = buttonsCustomLayout.at(i);
        setButtonLayout(array.constData(), array.count());
    } else {
        // Positions:
        //     Help Stretch Custom1 Custom2 Custom3 Cancel Back Next Commit Finish Cancel Help

        const int ArraySize = 12;
        QWizard::WizardButton array[ArraySize];
        memset(array, -1, sizeof(array));
        Q_ASSERT(array[0] == QWizard::NoButton);

        if (opts & QWizard::HaveHelpButton) {
            int i = (opts & QWizard::HelpButtonOnRight) ? 11 : 0;
            array[i] = QWizard::HelpButton;
        }
        array[1] = QWizard::Stretch;
        if (opts & QWizard::HaveCustomButton1)
            array[2] = QWizard::CustomButton1;
        if (opts & QWizard::HaveCustomButton2)
            array[3] = QWizard::CustomButton2;
        if (opts & QWizard::HaveCustomButton3)
            array[4] = QWizard::CustomButton3;

        if (!(opts & QWizard::NoCancelButton)) {
            int i = (opts & QWizard::CancelButtonOnLeft) ? 5 : 10;
            array[i] = QWizard::CancelButton;
        }
        array[6] = QWizard::BackButton;
        array[7] = QWizard::NextButton;
        array[8] = QWizard::CommitButton;
        array[9] = QWizard::FinishButton;

        setButtonLayout(array, ArraySize);
    }
}

void QWizardPrivate::setButtonLayout(const QWizard::WizardButton *array, int size)
{
    QWidget *prev = pageFrame;

    for (int i = buttonLayout->count() - 1; i >= 0; --i) {
        QLayoutItem *item = buttonLayout->takeAt(i);
        if (QWidget *widget = item->widget())
            widget->hide();
        delete item;
    }

    for (int i = 0; i < size; ++i) {
        QWizard::WizardButton which = array[i];
        if (which == QWizard::Stretch) {
            buttonLayout->addStretch(1);
        } else if (which != QWizard::NoButton) {
            ensureButton(which);
            buttonLayout->addWidget(btns[which]);

            // Back, Next, Commit, and Finish are handled in _q_updateButtonStates()
            if (which != QWizard::BackButton && which != QWizard::NextButton
                && which != QWizard::CommitButton && which != QWizard::FinishButton)
                btns[which]->show();

            if (prev)
                QWidget::setTabOrder(prev, btns[which]);
            prev = btns[which];
        }
    }

    _q_updateButtonStates();
}

bool QWizardPrivate::buttonLayoutContains(QWizard::WizardButton which)
{
    return !buttonsHaveCustomLayout || buttonsCustomLayout.contains(which);
}

void QWizardPrivate::updatePixmap(QWizard::WizardPixmap which)
{
    Q_Q(QWizard);
    if (which == QWizard::BackgroundPixmap) {
        if (wizStyle == QWizard::MacStyle) {
            q->update();
            q->updateGeometry();
        }
    } else {
        updateLayout();
    }
}

#if !defined(QT_NO_STYLE_WINDOWSVISTA)
bool QWizardPrivate::vistaDisabled() const
{
    Q_Q(const QWizard);
    const QVariant v = q->property("_q_wizard_vista_off");
    return v.isValid() && v.toBool();
}

bool QWizardPrivate::isVistaThemeEnabled(QVistaHelper::VistaState state) const
{
    return wizStyle == QWizard::AeroStyle
        && QVistaHelper::vistaState() == state
        && !vistaDisabled();
}

void QWizardPrivate::handleAeroStyleChange()
{
    Q_Q(QWizard);

    if (inHandleAeroStyleChange)
        return; // prevent recursion
    inHandleAeroStyleChange = true;

    vistaHelper->disconnectBackButton();
    q->removeEventFilter(vistaHelper);

    if (isVistaThemeEnabled()) {
        if (isVistaThemeEnabled(QVistaHelper::VistaAero)) {
            vistaHelper->setDWMTitleBar(QVistaHelper::ExtendedTitleBar);
            q->installEventFilter(vistaHelper);
            q->setMouseTracking(true);
            antiFlickerWidget->move(0, vistaHelper->titleBarSize() + vistaHelper->topOffset());
            vistaHelper->backButton()->move(
                0, vistaHelper->topOffset() // ### should ideally work without the '+ 1'
                - qMin(vistaHelper->topOffset(), vistaHelper->topPadding() + 1));
        } else {
            vistaHelper->setDWMTitleBar(QVistaHelper::NormalTitleBar);
            q->setMouseTracking(true);
            antiFlickerWidget->move(0, vistaHelper->topOffset());
            vistaHelper->backButton()->move(0, -1); // ### should ideally work with (0, 0)
        }
        vistaHelper->setTitleBarIconAndCaptionVisible(false);
        QObject::connect(
            vistaHelper->backButton(), SIGNAL(clicked()), q, buttonSlots[QWizard::BackButton]);
        vistaHelper->backButton()->show();
    } else {
        q->setMouseTracking(true); // ### original value possibly different
        q->unsetCursor(); // ### ditto
        antiFlickerWidget->move(0, 0);
        vistaHelper->hideBackButton();
        vistaHelper->setTitleBarIconAndCaptionVisible(true);
    }

    _q_updateButtonStates();

    if (q->isVisible())
        vistaHelper->setWindowPosHack();

    inHandleAeroStyleChange = false;
}
#endif

bool QWizardPrivate::isVistaThemeEnabled() const
{
#if !defined(QT_NO_STYLE_WINDOWSVISTA)
    return isVistaThemeEnabled(QVistaHelper::VistaAero)
        || isVistaThemeEnabled(QVistaHelper::VistaBasic);
#else
    return false;
#endif
}

void QWizardPrivate::disableUpdates()
{
    Q_Q(QWizard);
    if (disableUpdatesCount++ == 0) {
        q->setUpdatesEnabled(false);
        antiFlickerWidget->hide();
    }
}

void QWizardPrivate::enableUpdates()
{
    Q_Q(QWizard);
    if (--disableUpdatesCount == 0) {
        antiFlickerWidget->show();
        q->setUpdatesEnabled(true);
    }
}

void QWizardPrivate::_q_emitCustomButtonClicked()
{
    Q_Q(QWizard);
    QObject *button = q->sender();
    for (int i = QWizard::NStandardButtons; i < QWizard::NButtons; ++i) {
        if (btns[i] == button) {
            emit q->customButtonClicked(QWizard::WizardButton(i));
            break;
        }
    }
}

void QWizardPrivate::_q_updateButtonStates()
{
    Q_Q(QWizard);

    disableUpdates();

    const QWizardPage *page = q->currentPage();
    bool complete = page && page->isComplete();

    btn.back->setEnabled(history.count() > 1
                         && !q->page(history.at(history.count() - 2))->isCommitPage()
                         && (!canFinish || !(opts & QWizard::DisabledBackButtonOnLastPage)));
    btn.next->setEnabled(canContinue && complete);
    btn.commit->setEnabled(canContinue && complete);
    btn.finish->setEnabled(canFinish && complete);

    const bool backButtonVisible = buttonLayoutContains(QWizard::BackButton)
        && (history.count() > 1 || !(opts & QWizard::NoBackButtonOnStartPage))
        && (canContinue || !(opts & QWizard::NoBackButtonOnLastPage));
    bool commitPage = page && page->isCommitPage();
    btn.back->setVisible(backButtonVisible);
    btn.next->setVisible(buttonLayoutContains(QWizard::NextButton) && !commitPage
                         && (canContinue || (opts & QWizard::HaveNextButtonOnLastPage)));
    btn.commit->setVisible(buttonLayoutContains(QWizard::CommitButton) && commitPage
                           && canContinue);
    btn.finish->setVisible(buttonLayoutContains(QWizard::FinishButton)
                           && (canFinish || (opts & QWizard::HaveFinishButtonOnEarlyPages)));

    bool useDefault = !(opts & QWizard::NoDefaultButton);
    if (QPushButton *nextPush = qobject_cast<QPushButton *>(btn.next))
        nextPush->setDefault(canContinue && useDefault && !commitPage);
    if (QPushButton *commitPush = qobject_cast<QPushButton *>(btn.commit))
        commitPush->setDefault(canContinue && useDefault && commitPage);
    if (QPushButton *finishPush = qobject_cast<QPushButton *>(btn.finish))
        finishPush->setDefault(!canContinue && useDefault);

#if !defined(QT_NO_STYLE_WINDOWSVISTA)
    if (isVistaThemeEnabled()) {
        vistaHelper->backButton()->setEnabled(btn.back->isEnabled());
        vistaHelper->backButton()->setVisible(backButtonVisible);
        btn.back->setVisible(false);
    }
#endif

#ifdef QT_SOFTKEYS_ENABLED
    QAbstractButton *wizardButton;
    for (int i = 0; i < QWizard::NButtons; ++i) {
        wizardButton = btns[i];
        if (wizardButton && !wizardButton->testAttribute(Qt::WA_WState_Hidden)) {
            wizardButton->hide();
            q->addAction(softKeys[i]);
        } else {
            q->removeAction(softKeys[i]);
        }
    }
#endif

    enableUpdates();
}

void QWizardPrivate::_q_handleFieldObjectDestroyed(QObject *object)
{
    QVector<QWizardField>::iterator it = fields.begin();
    while (it != fields.end()) {
        const QWizardField &field = *it;
        if (field.object == object) {
            fieldIndexMap.remove(field.name);
            it = fields.erase(it);
        } else {
            ++it;
        }
    }
}

void QWizardPrivate::setStyle(QStyle *style)
{
    for (int i = 0; i < QWizard::NButtons; i++)
        if (btns[i])
            btns[i]->setStyle(style);
    const PageMap::const_iterator pcend = pageMap.constEnd();
    for (PageMap::const_iterator it = pageMap.constBegin(); it != pcend; ++it)
        it.value()->setStyle(style);
}

#ifdef Q_WS_MAC

QPixmap QWizardPrivate::findDefaultBackgroundPixmap()
{
    QCFType<CFURLRef> url;
    const int ExpectedImageWidth = 242;
    const int ExpectedImageHeight = 414;
    if (LSFindApplicationForInfo(kLSUnknownCreator, CFSTR("com.apple.KeyboardSetupAssistant"),
                                 0, 0, &url) == noErr) {
        QCFType<CFBundleRef> bundle = CFBundleCreate(kCFAllocatorDefault, url);
        if (bundle) {
            url = CFBundleCopyResourceURL(bundle, CFSTR("Background"), CFSTR("tif"), 0);
            if (url) {
                QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithURL(url, 0);
                QCFType<CGImageRef> image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0);
                if (image) {
                    int width = CGImageGetWidth(image);
                    int height = CGImageGetHeight(image);
                    if (width == ExpectedImageWidth && height == ExpectedImageHeight)
                        return QPixmap::fromMacCGImageRef(image);
                }
            }
        }
    }
    return QPixmap();

}

#endif

#if !defined(QT_NO_STYLE_WINDOWSVISTA)
void QWizardAntiFlickerWidget::paintEvent(QPaintEvent *)
{
    if (wizardPrivate->isVistaThemeEnabled()) {
        int leftMargin, topMargin, rightMargin, bottomMargin;
        wizardPrivate->buttonLayout->getContentsMargins(
            &leftMargin, &topMargin, &rightMargin, &bottomMargin);
        const int buttonLayoutTop = wizardPrivate->buttonLayout->contentsRect().top() - topMargin;
        QPainter painter(this);
        const QBrush brush(QColor(240, 240, 240)); // ### hardcoded for now
        painter.fillRect(0, buttonLayoutTop, width(), height() - buttonLayoutTop, brush);
        painter.setPen(QPen(QBrush(QColor(223, 223, 223)), 0)); // ### hardcoded for now
        painter.drawLine(0, buttonLayoutTop, width(), buttonLayoutTop);
        if (wizardPrivate->isVistaThemeEnabled(QVistaHelper::VistaBasic)) {
            if (window()->isActiveWindow())
                painter.setPen(QPen(QBrush(QColor(169, 191, 214)), 0)); // ### hardcoded for now
            else
                painter.setPen(QPen(QBrush(QColor(182, 193, 204)), 0)); // ### hardcoded for now
            painter.drawLine(0, 0, width(), 0);
        }
    }
}
#endif

/*!
    \class QWizard
    \since 4.3
    \brief The QWizard class provides a framework for wizards.

    A wizard (also called an assistant on Mac OS X) is a special type
    of input dialog that consists of a sequence of pages. A wizard's
    purpose is to guide the user through a process step by step.
    Wizards are useful for complex or infrequent tasks that users may
    find difficult to learn.

    QWizard inherits QDialog and represents a wizard. Each page is a
    QWizardPage (a QWidget subclass). To create your own wizards, you
    can use these classes directly, or you can subclass them for more
    control.

    Topics:

    \tableofcontents

    \section1 A Trivial Example

    The following example illustrates how to create wizard pages and
    add them to a wizard. For more advanced examples, see
    \l{dialogs/classwizard}{Class Wizard} and \l{dialogs/licensewizard}{License
    Wizard}.

    \snippet examples/dialogs/trivialwizard/trivialwizard.cpp 1
    \snippet examples/dialogs/trivialwizard/trivialwizard.cpp 3
    \dots
    \snippet examples/dialogs/trivialwizard/trivialwizard.cpp 4
    \codeline
    \snippet examples/dialogs/trivialwizard/trivialwizard.cpp 5
    \snippet examples/dialogs/trivialwizard/trivialwizard.cpp 7
    \dots
    \snippet examples/dialogs/trivialwizard/trivialwizard.cpp 8
    \codeline
    \snippet examples/dialogs/trivialwizard/trivialwizard.cpp 10

    \section1 Wizard Look and Feel

    QWizard supports four wizard looks:

    \list
    \o ClassicStyle
    \o ModernStyle
    \o MacStyle
    \o AeroStyle
    \endlist

    You can explicitly set the look to use using setWizardStyle()
    (e.g., if you want the same look on all platforms).

    \table
    \header \o ClassicStyle
            \o ModernStyle
            \o MacStyle
            \o AeroStyle
    \row    \o \inlineimage qtwizard-classic1.png
            \o \inlineimage qtwizard-modern1.png
            \o \inlineimage qtwizard-mac1.png
            \o \inlineimage qtwizard-aero1.png
    \row    \o \inlineimage qtwizard-classic2.png
            \o \inlineimage qtwizard-modern2.png
            \o \inlineimage qtwizard-mac2.png
            \o \inlineimage qtwizard-aero2.png
    \endtable

    Note: AeroStyle has effect only on a Windows Vista system with alpha compositing enabled.
    ModernStyle is used as a fallback when this condition is not met.

    In addition to the wizard style, there are several options that
    control the look and feel of the wizard. These can be set using
    setOption() or setOptions(). For example, HaveHelpButton makes
    QWizard show a \gui Help button along with the other wizard
    buttons.

    You can even change the order of the wizard buttons to any
    arbitrary order using setButtonLayout(), and you can add up to
    three custom buttons (e.g., a \gui Print button) to the button
    row. This is achieved by calling setButton() or setButtonText()
    with CustomButton1, CustomButton2, or CustomButton3 to set up the
    button, and by enabling the HaveCustomButton1, HaveCustomButton2,
    or HaveCustomButton3 options. Whenever the user clicks a custom
    button, customButtonClicked() is emitted. For example:

    \snippet examples/dialogs/licensewizard/licensewizard.cpp 29

    \section1 Elements of a Wizard Page

    Wizards consist of a sequence of \l{QWizardPage}s. At any time,
    only one page is shown. A page has the following attributes:

    \list
    \o A \l{QWizardPage::}{title}.
    \o A \l{QWizardPage::}{subTitle}.
    \o A set of pixmaps, which may or may not be honored, depending
       on the wizard's style:
        \list
        \o WatermarkPixmap (used by ClassicStyle and ModernStyle)
        \o BannerPixmap (used by ModernStyle)
        \o LogoPixmap (used by ClassicStyle and ModernStyle)
        \o BackgroundPixmap (used by MacStyle)
        \endlist
    \endlist

    The diagram belows shows how QWizard renders these attributes,
    assuming they are all present and ModernStyle is used:

    \image qtwizard-nonmacpage.png

    When a \l{QWizardPage::}{subTitle} is set, QWizard displays it
    in a header, in which case it also uses the BannerPixmap and the
    LogoPixmap to decorate the header. The WatermarkPixmap is
    displayed on the left side, below the header. At the bottom,
    there is a row of buttons allowing the user to navigate through
    the pages.

    The page itself (the \l{QWizardPage} widget) occupies the area
    between the header, the watermark, and the button row. Typically,
    the page is a QWizardPage on which a QGridLayout is installed,
    with standard child widgets (\l{QLabel}s, \l{QLineEdit}s, etc.).

    If the wizard's style is MacStyle, the page looks radically
    different:

    \image qtwizard-macpage.png

    The watermark, banner, and logo pixmaps are ignored by the
    MacStyle. If the BackgroundPixmap is set, it is used as the
    background for the wizard; otherwise, a default "assistant" image
    is used.

    The title and subtitle are set by calling
    QWizardPage::setTitle() and QWizardPage::setSubTitle() on the
    individual pages. They may be plain text or HTML (see titleFormat
    and subTitleFormat). The pixmaps can be set globally for the
    entire wizard using setPixmap(), or on a per-page basis using
    QWizardPage::setPixmap().

    \target field mechanism
    \section1 Registering and Using Fields

    In many wizards, the contents of a page may affect the default
    values of the fields of a later page. To make it easy to
    communicate between pages, QWizard supports a "field" mechanism
    that allows you to register a field (e.g., a QLineEdit) on a page
    and to access its value from any page. It is also possible to
    specify mandatory fields (i.e., fields that must be filled before
    the user can advance to the next page).

    To register a field, call QWizardPage::registerField() field.
    For example:

    \snippet examples/dialogs/classwizard/classwizard.cpp 8
    \dots
    \snippet examples/dialogs/classwizard/classwizard.cpp 10
    \snippet examples/dialogs/classwizard/classwizard.cpp 11
    \dots
    \snippet examples/dialogs/classwizard/classwizard.cpp 13

    The above code registers three fields, \c className, \c
    baseClass, and \c qobjectMacro, which are associated with three
    child widgets. The asterisk (\c *) next to \c className denotes a
    mandatory field.

    \target initialize page
    The fields of any page are accessible from any other page. For
    example:

    \snippet examples/dialogs/classwizard/classwizard.cpp 17

    Here, we call QWizardPage::field() to access the contents of the
    \c className field (which was defined in the \c ClassInfoPage)
    and use it to initialize the \c OuputFilePage. The field's
    contents is returned as a QVariant.

    When we create a field using QWizardPage::registerField(), we
    pass a unique field name and a widget. We can also provide a Qt
    property name and a "changed" signal (a signal that is emitted
    when the property changes) as third and fourth arguments;
    however, this is not necessary for the most common Qt widgets,
    such as QLineEdit, QCheckBox, and QComboBox, because QWizard
    knows which properties to look for.

    \target mandatory fields

    If an asterisk (\c *) is appended to the name when the property
    is registered, the field is a \e{mandatory field}. When a page has
    mandatory fields, the \gui Next and/or \gui Finish buttons are
    enabled only when all mandatory fields are filled.

    To consider a field "filled", QWizard simply checks that the
    field's current value doesn't equal the original value (the value
    it had when initializePage() was called). For QLineEdit and
    QAbstractSpinBox subclasses, QWizard also checks that
    \l{QLineEdit::hasAcceptableInput()}{hasAcceptableInput()} returns
    true, to honor any validator or mask.

    QWizard's mandatory field mechanism is provided for convenience.
    A more powerful (but also more cumbersome) alternative is to
    reimplement QWizardPage::isComplete() and to emit the
    QWizardPage::completeChanged() signal whenever the page becomes
    complete or incomplete.

    The enabled/disabled state of the \gui Next and/or \gui Finish
    buttons is one way to perform validation on the user input.
    Another way is to reimplement validateCurrentPage() (or
    QWizardPage::validatePage()) to perform some last-minute
    validation (and show an error message if the user has entered
    incomplete or invalid information). If the function returns true,
    the next page is shown (or the wizard finishes); otherwise, the
    current page stays up.

    \section1 Creating Linear Wizards

    Most wizards have a linear structure, with page 1 followed by
    page 2 and so on until the last page. The \l{dialogs/classwizard}{Class
    Wizard} example is such a wizard. With QWizard, linear wizards
    are created by instantiating the \l{QWizardPage}s and inserting
    them using addPage(). By default, the pages are shown in the
    order in which they were added. For example:

    \snippet examples/dialogs/classwizard/classwizard.cpp 0
    \dots
    \snippet examples/dialogs/classwizard/classwizard.cpp 2

    When a page is about to be shown, QWizard calls initializePage()
    (which in turn calls QWizardPage::initializePage()) to fill the
    page with default values. By default, this function does nothing,
    but it can be reimplemented to initialize the page's contents
    based on other pages' fields (see the \l{initialize page}{example
    above}).

    If the user presses \gui Back, cleanupPage() is called (which in
    turn calls QWizardPage::cleanupPage()). The default
    implementation resets the page's fields to their original values
    (the values they had before initializePage() was called). If you
    want the \gui Back button to be non-destructive and keep the
    values entered by the user, simply enable the IndependentPages
    option.

    \section1 Creating Non-Linear Wizards

    Some wizards are more complex in that they allow different
    traversal paths based on the information provided by the user.
    The \l{dialogs/licensewizard}{License Wizard} example illustrates this.
    It provides five wizard pages; depending on which options are
    selected, the user can reach different pages.

    \image licensewizard-flow.png

    In complex wizards, pages are identified by IDs. These IDs are
    typically defined using an enum. For example:

    \snippet examples/dialogs/licensewizard/licensewizard.h 0
    \dots
    \snippet examples/dialogs/licensewizard/licensewizard.h 2
    \dots
    \snippet examples/dialogs/licensewizard/licensewizard.h 3

    The pages are inserted using setPage(), which takes an ID and an
    instance of QWizardPage (or of a subclass):

    \snippet examples/dialogs/licensewizard/licensewizard.cpp 1
    \dots
    \snippet examples/dialogs/licensewizard/licensewizard.cpp 8

    By default, the pages are shown in increasing ID order. To
    provide a dynamic order that depends on the options chosen by the
    user, we must reimplement QWizardPage::nextId(). For example:

    \snippet examples/dialogs/licensewizard/licensewizard.cpp 18
    \codeline
    \snippet examples/dialogs/licensewizard/licensewizard.cpp 23
    \codeline
    \snippet examples/dialogs/licensewizard/licensewizard.cpp 24
    \codeline
    \snippet examples/dialogs/licensewizard/licensewizard.cpp 25
    \codeline
    \snippet examples/dialogs/licensewizard/licensewizard.cpp 26

    It would also be possible to put all the logic in one place, in a
    QWizard::nextId() reimplementation. For example:

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

    To start at another page than the page with the lowest ID, call
    setStartId().

    To test whether a page has been visited or not, call
    hasVisitedPage(). For example:

    \snippet examples/dialogs/licensewizard/licensewizard.cpp 27

    \sa QWizardPage, {Class Wizard Example}, {License Wizard Example}
*/

/*!
    \enum QWizard::WizardButton

    This enum specifies the buttons in a wizard.

    \value BackButton  The \gui Back button (\gui {Go Back} on Mac OS X)
    \value NextButton  The \gui Next button (\gui Continue on Mac OS X)
    \value CommitButton  The \gui Commit button
    \value FinishButton  The \gui Finish button (\gui Done on Mac OS X)
    \value CancelButton  The \gui Cancel button (see also NoCancelButton)
    \value HelpButton    The \gui Help button (see also HaveHelpButton)
    \value CustomButton1  The first user-defined button (see also HaveCustomButton1)
    \value CustomButton2  The second user-defined button (see also HaveCustomButton2)
    \value CustomButton3  The third user-defined button (see also HaveCustomButton3)

    The following value is only useful when calling setButtonLayout():

    \value Stretch  A horizontal stretch in the button layout

    \omitvalue NoButton
    \omitvalue NStandardButtons
    \omitvalue NButtons

    \sa setButton(), setButtonText(), setButtonLayout(), customButtonClicked()
*/

/*!
    \enum QWizard::WizardPixmap

    This enum specifies the pixmaps that can be associated with a page.

    \value WatermarkPixmap  The tall pixmap on the left side of a ClassicStyle or ModernStyle page
    \value LogoPixmap  The small pixmap on the right side of a ClassicStyle or ModernStyle page header
    \value BannerPixmap  The pixmap that occupies the background of a ModernStyle page header
    \value BackgroundPixmap  The pixmap that occupies the background of a MacStyle wizard

    \omitvalue NPixmaps

    \sa setPixmap(), QWizardPage::setPixmap(), {Elements of a Wizard Page}
*/

/*!
    \enum QWizard::WizardStyle

    This enum specifies the different looks supported by QWizard.

    \value ClassicStyle  Classic Windows look
    \value ModernStyle  Modern Windows look
    \value MacStyle  Mac OS X look
    \value AeroStyle  Windows Aero look

    \omitvalue NStyles

    \sa setWizardStyle(), WizardOption, {Wizard Look and Feel}
*/

/*!
    \enum QWizard::WizardOption

    This enum specifies various options that affect the look and feel
    of a wizard.

    \value IndependentPages  The pages are independent of each other
                             (i.e., they don't derive values from each
                             other).
    \value IgnoreSubTitles  Don't show any subtitles, even if they are set.
    \value ExtendedWatermarkPixmap  Extend any WatermarkPixmap all the
                                    way down to the window's edge.
    \value NoDefaultButton  Don't make the \gui Next or \gui Finish button the
                            dialog's \l{QPushButton::setDefault()}{default button}.
    \value NoBackButtonOnStartPage  Don't show the \gui Back button on the start page.
    \value NoBackButtonOnLastPage   Don't show the \gui Back button on the last page.
    \value DisabledBackButtonOnLastPage  Disable the \gui Back button on the last page.
    \value HaveNextButtonOnLastPage  Show the (disabled) \gui Next button on the last page.
    \value HaveFinishButtonOnEarlyPages  Show the (disabled) \gui Finish button on non-final pages.
    \value NoCancelButton  Don't show the \gui Cancel button.
    \value CancelButtonOnLeft  Put the \gui Cancel button on the left of \gui Back (rather than on
                               the right of \gui Finish or \gui Next).
    \value HaveHelpButton  Show the \gui Help button.
    \value HelpButtonOnRight  Put the \gui Help button on the far right of the button layout
                              (rather than on the far left).
    \value HaveCustomButton1  Show the first user-defined button (CustomButton1).
    \value HaveCustomButton2  Show the second user-defined button (CustomButton2).
    \value HaveCustomButton3  Show the third user-defined button (CustomButton3).

    \sa setOptions(), setOption(), testOption()
*/

/*!
    Constructs a wizard with the given \a parent and window \a flags.

    \sa parent(), windowFlags()
*/
QWizard::QWizard(QWidget *parent, Qt::WindowFlags flags)
    : QDialog(*new QWizardPrivate, parent, flags)
{
    Q_D(QWizard);
    d->init();
#ifdef Q_WS_WINCE
    if (!qt_wince_is_mobile())
        setWindowFlags(windowFlags() & ~Qt::WindowOkButtonHint);
#endif
}

/*!
    Destroys the wizard and its pages, releasing any allocated resources.
*/
QWizard::~QWizard()
{
    Q_D(QWizard);
    delete d->buttonLayout;
}

/*!
    Adds the given \a page to the wizard, and returns the page's ID.

    The ID is guaranteed to be larger than any other ID in the
    QWizard so far.

    \sa setPage(), page()
*/
int QWizard::addPage(QWizardPage *page)
{
    Q_D(QWizard);
    int theid = 0;
    if (!d->pageMap.isEmpty())
        theid = (d->pageMap.constEnd() - 1).key() + 1;
    setPage(theid, page);
    return theid;
}

/*!
    \fn void QWizard::setPage(int id, QWizardPage *page)

    Adds the given \a page to the wizard with the given \a id.

    \sa addPage(), page()
*/
void QWizard::setPage(int theid, QWizardPage *page)
{
    Q_D(QWizard);

    if (!page) {
        qWarning("QWizard::setPage: Cannot insert null page");
        return;
    }

    if (theid == -1) {
        qWarning("QWizard::setPage: Cannot insert page with ID -1");
        return;
    }

    if (d->pageMap.contains(theid)) {
        qWarning("QWizard::setPage: Page with duplicate ID %d ignored", theid);
        return;
    }

    page->setParent(d->pageFrame);

    QVector<QWizardField> &pendingFields = page->d_func()->pendingFields;
    for (int i = 0; i < pendingFields.count(); ++i)
        d->addField(pendingFields.at(i));
    pendingFields.clear();

    connect(page, SIGNAL(completeChanged()), this, SLOT(_q_updateButtonStates()));

    d->pageMap.insert(theid, page);
    page->d_func()->wizard = this;

    int n = d->pageVBoxLayout->count();

    // disable layout to prevent layout updates while adding
    bool pageVBoxLayoutEnabled = d->pageVBoxLayout->isEnabled();
    d->pageVBoxLayout->setEnabled(false);

    d->pageVBoxLayout->insertWidget(n - 1, page);

    // hide new page and reset layout to old status
    page->hide();
    d->pageVBoxLayout->setEnabled(pageVBoxLayoutEnabled);
}

/*!
    Removes the page with the given \a id. cleanupPage() will be called if necessary.
    \since 4.5
    \sa addPage(), setPage()
*/
void QWizard::removePage(int id)
{
    Q_D(QWizard);

    QWizardPage *removedPage = 0;

    if (d->start == id)
        d->start = -1;

    if (!d->history.contains(id)) {
        // Case 1: removing a page not in the history
        removedPage = d->pageMap.take(id);
        d->updateCurrentPage();
    } else if (id != d->current) {
        // Case 2: removing a page in the history before the current page
        removedPage = d->pageMap.take(id);
        d->history.removeOne(id);
        d->_q_updateButtonStates();
    } else if (d->history.count() == 1) {
        // Case 3: removing the current page which is the first (and only) one in the history
        d->reset();
        removedPage = d->pageMap.take(id);
        if (d->pageMap.isEmpty())
            d->updateCurrentPage();
        else
            restart();
    } else {
        // Case 4: removing the current page which is not the first one in the history
        back();
        removedPage = d->pageMap.take(id);
        d->updateCurrentPage();
    }

    if (removedPage) {
        if (d->initialized.contains(id)) {
            cleanupPage(id);
            d->initialized.remove(id);
        }

        d->pageVBoxLayout->removeWidget(removedPage);

        for (int i = d->fields.count() - 1; i >= 0; --i) {
            if (d->fields.at(i).page == removedPage) {
                removedPage->d_func()->pendingFields += d->fields.at(i);
                d->removeFieldAt(i);
            }
        }
    }
}

/*!
    \fn QWizardPage *QWizard::page(int id) const

    Returns the page with the given \a id, or 0 if there is no such
    page.

    \sa addPage(), setPage()
*/
QWizardPage *QWizard::page(int theid) const
{
    Q_D(const QWizard);
    return d->pageMap.value(theid);
}

/*!
    \fn bool QWizard::hasVisitedPage(int id) const

    Returns true if the page history contains page \a id; otherwise,
    returns false.

    Pressing \gui Back marks the current page as "unvisited" again.

    \sa visitedPages()
*/
bool QWizard::hasVisitedPage(int theid) const
{
    Q_D(const QWizard);
    return d->history.contains(theid);
}

/*!
    Returns the list of IDs of visited pages, in the order in which the pages
    were visited.

    Pressing \gui Back marks the current page as "unvisited" again.

    \sa hasVisitedPage()
*/
QList<int> QWizard::visitedPages() const
{
    Q_D(const QWizard);
    return d->history;
}

/*!
    Returns the list of page IDs.
   \since 4.5
*/
QList<int> QWizard::pageIds() const
{
  Q_D(const QWizard);
  return d->pageMap.keys();
}

/*!
    \property QWizard::startId
    \brief the ID of the first page

    If this property isn't explicitly set, this property defaults to
    the lowest page ID in this wizard, or -1 if no page has been
    inserted yet.

    \sa restart(), nextId()
*/
void QWizard::setStartId(int theid)
{
    Q_D(QWizard);
    if (!d->pageMap.contains(theid)) {
        qWarning("QWizard::setStartId: Invalid page ID %d", theid);
        return;
    }
    d->start = theid;
}

int QWizard::startId() const
{
    Q_D(const QWizard);
    if (d->start != -1)
        return d->start;
    if (!d->pageMap.isEmpty())
        return d->pageMap.constBegin().key();
    return -1;
}

/*!
    Returns a pointer to the current page, or 0 if there is no current
    page (e.g., before the wizard is shown).

    This is equivalent to calling page(currentId()).

    \sa page(), currentId(), restart()
*/
QWizardPage *QWizard::currentPage() const
{
    Q_D(const QWizard);
    return page(d->current);
}

/*!
    \property QWizard::currentId
    \brief the ID of the current page

    This property cannot be set directly. To change the current page,
    call next(), back(), or restart().

    By default, this property has a value of -1, indicating that no page is
    currently shown.

    \sa currentIdChanged(), currentPage()
*/
int QWizard::currentId() const
{
    Q_D(const QWizard);
    return d->current;
}

/*!
    Sets the value of the field called \a name to \a value.

    This function can be used to set fields on any page of the wizard.

    \sa QWizardPage::registerField(), QWizardPage::setField(), field()
*/
void QWizard::setField(const QString &name, const QVariant &value)
{
    Q_D(QWizard);

    int index = d->fieldIndexMap.value(name, -1);
    if (index != -1) {
        const QWizardField &field = d->fields.at(index);
        if (!field.object->setProperty(field.property, value))
            qWarning("QWizard::setField: Couldn't write to property '%s'",
                     field.property.constData());
        return;
    }

    qWarning("QWizard::setField: No such field '%s'", qPrintable(name));
}

/*!
    Returns the value of the field called \a name.

    This function can be used to access fields on any page of the wizard.

    \sa QWizardPage::registerField(), QWizardPage::field(), setField()
*/
QVariant QWizard::field(const QString &name) const
{
    Q_D(const QWizard);

    int index = d->fieldIndexMap.value(name, -1);
    if (index != -1) {
        const QWizardField &field = d->fields.at(index);
        return field.object->property(field.property);
    }

    qWarning("QWizard::field: No such field '%s'", qPrintable(name));
    return QVariant();
}

/*!
    \property QWizard::wizardStyle
    \brief the look and feel of the wizard

    By default, QWizard uses the AeroStyle on a Windows Vista system with alpha compositing
    enabled, regardless of the current widget style. If this is not the case, the default
    wizard style depends on the current widget style as follows: MacStyle is the default if
    the current widget style is QMacStyle, ModernStyle is the default if the current widget
    style is QWindowsStyle, and ClassicStyle is the default in all other cases.

    \sa {Wizard Look and Feel}, options
*/
void QWizard::setWizardStyle(WizardStyle style)
{
    Q_D(QWizard);

    const bool styleChange = style != d->wizStyle;

#if !defined(QT_NO_STYLE_WINDOWSVISTA)
    const bool aeroStyleChange =
        d->vistaInitPending || d->vistaStateChanged || (styleChange && (style == AeroStyle || d->wizStyle == AeroStyle));
    d->vistaStateChanged = false;
    d->vistaInitPending = false;
#endif

    if (styleChange
#if !defined(QT_NO_STYLE_WINDOWSVISTA)
        || aeroStyleChange
#endif
        ) {
        d->disableUpdates();
        d->wizStyle = style;
        d->updateButtonTexts();
        d->updateLayout();
        updateGeometry();
        d->enableUpdates();
#if !defined(QT_NO_STYLE_WINDOWSVISTA)
        if (aeroStyleChange)
            d->handleAeroStyleChange();
#endif
    }
}

QWizard::WizardStyle QWizard::wizardStyle() const
{
    Q_D(const QWizard);
    return d->wizStyle;
}

/*!
    Sets the given \a option to be enabled if \a on is true;
    otherwise, clears the given \a option.

    \sa options, testOption(), setWizardStyle()
*/
void QWizard::setOption(WizardOption option, bool on)
{
    Q_D(QWizard);
    if (!(d->opts & option) != !on)
        setOptions(d->opts ^ option);
}

/*!
    Returns true if the given \a option is enabled; otherwise, returns
    false.

    \sa options, setOption(), setWizardStyle()
*/
bool QWizard::testOption(WizardOption option) const
{
    Q_D(const QWizard);
    return (d->opts & option) != 0;
}

/*!
    \property QWizard::options
    \brief the various options that affect the look and feel of the wizard

    By default, the following options are set (depending on the platform):

    \list
    \o Windows: HelpButtonOnRight.
    \o Mac OS X: NoDefaultButton and NoCancelButton.
    \o X11 and QWS (Qt for Embedded Linux): none.
    \endlist

    \sa wizardStyle
*/
void QWizard::setOptions(WizardOptions options)
{
    Q_D(QWizard);

    WizardOptions changed = (options ^ d->opts);
    if (!changed)
        return;

    d->disableUpdates();

    d->opts = options;
    if ((changed & IndependentPages) && !(d->opts & IndependentPages))
        d->cleanupPagesNotInHistory();

    if (changed & (NoDefaultButton | HaveHelpButton | HelpButtonOnRight | NoCancelButton
                   | CancelButtonOnLeft | HaveCustomButton1 | HaveCustomButton2
                   | HaveCustomButton3)) {
        d->updateButtonLayout();
    } else if (changed & (NoBackButtonOnStartPage | NoBackButtonOnLastPage
                          | HaveNextButtonOnLastPage | HaveFinishButtonOnEarlyPages
                          | DisabledBackButtonOnLastPage)) {
        d->_q_updateButtonStates();
    }

    d->enableUpdates();
    d->updateLayout();
}

QWizard::WizardOptions QWizard::options() const
{
    Q_D(const QWizard);
    return d->opts;
}

/*!
    Sets the text on button \a which to be \a text.

    By default, the text on buttons depends on the wizardStyle. For
    example, on Mac OS X, the \gui Next button is called \gui
    Continue.

    To add extra buttons to the wizard (e.g., a \gui Print button),
    one way is to call setButtonText() with CustomButton1,
    CustomButton2, or CustomButton3 to set their text, and make the
    buttons visible using the HaveCustomButton1, HaveCustomButton2,
    and/or HaveCustomButton3 options.

    Button texts may also be set on a per-page basis using QWizardPage::setButtonText().

    \sa setButton(), button(), setButtonLayout(), setOptions(), QWizardPage::setButtonText()
*/
void QWizard::setButtonText(WizardButton which, const QString &text)
{
    Q_D(QWizard);

    if (!d->ensureButton(which))
        return;

    d->buttonCustomTexts.insert(which, text);

    if (!currentPage() || !currentPage()->d_func()->buttonCustomTexts.contains(which))
        d->btns[which]->setText(text);
}

/*!
    Returns the text on button \a which.

    If a text has ben set using setButtonText(), this text is returned.

    By default, the text on buttons depends on the wizardStyle. For
    example, on Mac OS X, the \gui Next button is called \gui
    Continue.

    \sa button(), setButton(), setButtonText(), QWizardPage::buttonText(),
    QWizardPage::setButtonText()
*/
QString QWizard::buttonText(WizardButton which) const
{
    Q_D(const QWizard);

    if (!d->ensureButton(which))
        return QString();

    if (d->buttonCustomTexts.contains(which))
        return d->buttonCustomTexts.value(which);

    const QString defText = buttonDefaultText(d->wizStyle, which, d);
    if(!defText.isNull())
        return defText;

    return d->btns[which]->text();
}

/*!
    Sets the order in which buttons are displayed to \a layout, where
    \a layout is a list of \l{WizardButton}s.

    The default layout depends on the options (e.g., whether
    HelpButtonOnRight) that are set. You can call this function if
    you need more control over the buttons' layout than what \l
    options already provides.

    You can specify horizontal stretches in the layout using \l
    Stretch.

    Example:

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

    \sa setButton(), setButtonText(), setOptions()
*/
void QWizard::setButtonLayout(const QList<WizardButton> &layout)
{
    Q_D(QWizard);

    for (int i = 0; i < layout.count(); ++i) {
        WizardButton button1 = layout.at(i);

        if (button1 == NoButton || button1 == Stretch)
            continue;
        if (!d->ensureButton(button1))
            return;

        // O(n^2), but n is very small
        for (int j = 0; j < i; ++j) {
            WizardButton button2 = layout.at(j);
            if (button2 == button1) {
                qWarning("QWizard::setButtonLayout: Duplicate button in layout");
                return;
            }
        }
    }

    d->buttonsHaveCustomLayout = true;
    d->buttonsCustomLayout = layout;
    d->updateButtonLayout();
}

/*!
    Sets the button corresponding to role \a which to \a button.

    To add extra buttons to the wizard (e.g., a \gui Print button),
    one way is to call setButton() with CustomButton1 to
    CustomButton3, and make the buttons visible using the
    HaveCustomButton1 to HaveCustomButton3 options.

    \sa setButtonText(), setButtonLayout(), options
*/
void QWizard::setButton(WizardButton which, QAbstractButton *button)
{
    Q_D(QWizard);

    if (uint(which) >= NButtons || d->btns[which] == button)
        return;

    if (QAbstractButton *oldButton = d->btns[which]) {
        d->buttonLayout->removeWidget(oldButton);
        delete oldButton;
    }

    d->btns[which] = button;
    if (button) {
        button->setParent(d->antiFlickerWidget);
        d->buttonCustomTexts.insert(which, button->text());
        d->connectButton(which);
    } else {
        d->buttonCustomTexts.remove(which); // ### what about page-specific texts set for 'which'
        d->ensureButton(which);             // (QWizardPage::setButtonText())? Clear them as well?
    }

    d->updateButtonLayout();
}

/*!
    Returns the button corresponding to role \a which.

    \sa setButton(), setButtonText()
*/
QAbstractButton *QWizard::button(WizardButton which) const
{
    Q_D(const QWizard);
#if !defined(QT_NO_STYLE_WINDOWSVISTA)
    if (d->wizStyle == AeroStyle && which == BackButton)
        return d->vistaHelper->backButton();
#endif
    if (!d->ensureButton(which))
        return 0;
    return d->btns[which];
}

/*!
    \property QWizard::titleFormat
    \brief the text format used by page titles

    The default format is Qt::AutoText.

    \sa QWizardPage::title, subTitleFormat
*/
void QWizard::setTitleFormat(Qt::TextFormat format)
{
    Q_D(QWizard);
    d->titleFmt = format;
    d->updateLayout();
}

Qt::TextFormat QWizard::titleFormat() const
{
    Q_D(const QWizard);
    return d->titleFmt;
}

/*!
    \property QWizard::subTitleFormat
    \brief the text format used by page subtitles

    The default format is Qt::AutoText.

    \sa QWizardPage::title, titleFormat
*/
void QWizard::setSubTitleFormat(Qt::TextFormat format)
{
    Q_D(QWizard);
    d->subTitleFmt = format;
    d->updateLayout();
}

Qt::TextFormat QWizard::subTitleFormat() const
{
    Q_D(const QWizard);
    return d->subTitleFmt;
}

/*!
    Sets the pixmap for role \a which to \a pixmap.

    The pixmaps are used by QWizard when displaying a page. Which
    pixmaps are actually used depend on the \l{Wizard Look and
    Feel}{wizard style}.

    Pixmaps can also be set for a specific page using
    QWizardPage::setPixmap().

    \sa QWizardPage::setPixmap(), {Elements of a Wizard Page}
*/
void QWizard::setPixmap(WizardPixmap which, const QPixmap &pixmap)
{
    Q_D(QWizard);
    Q_ASSERT(uint(which) < NPixmaps);
    d->defaultPixmaps[which] = pixmap;
    d->updatePixmap(which);
}

/*!
    Returns the pixmap set for role \a which.

    By default, the only pixmap that is set is the BackgroundPixmap on
    Mac OS X.

    \sa QWizardPage::pixmap(), {Elements of a Wizard Page}
*/
QPixmap QWizard::pixmap(WizardPixmap which) const
{
    Q_D(const QWizard);
    Q_ASSERT(uint(which) < NPixmaps);
#ifdef Q_WS_MAC
    if (which == BackgroundPixmap && d->defaultPixmaps[BackgroundPixmap].isNull())
        d->defaultPixmaps[BackgroundPixmap] = d->findDefaultBackgroundPixmap();
#endif
    return d->defaultPixmaps[which];
}

/*!
    Sets the default property for \a className to be \a property,
    and the associated change signal to be \a changedSignal.

    The default property is used when an instance of \a className (or
    of one of its subclasses) is passed to
    QWizardPage::registerField() and no property is specified.

    QWizard knows the most common Qt widgets. For these (or their
    subclasses), you don't need to specify a \a property or a \a
    changedSignal. The table below lists these widgets:

    \table
    \header \o Widget          \o Property                            \o Change Notification Signal
    \row    \o QAbstractButton \o bool \l{QAbstractButton::}{checked} \o \l{QAbstractButton::}{toggled()}
    \row    \o QAbstractSlider \o int \l{QAbstractSlider::}{value}    \o \l{QAbstractSlider::}{valueChanged()}
    \row    \o QComboBox       \o int \l{QComboBox::}{currentIndex}   \o \l{QComboBox::}{currentIndexChanged()}
    \row    \o QDateTimeEdit   \o QDateTime \l{QDateTimeEdit::}{dateTime} \o \l{QDateTimeEdit::}{dateTimeChanged()}
    \row    \o QLineEdit       \o QString \l{QLineEdit::}{text}       \o \l{QLineEdit::}{textChanged()}
    \row    \o QListWidget     \o int \l{QListWidget::}{currentRow}   \o \l{QListWidget::}{currentRowChanged()}
    \row    \o QSpinBox        \o int \l{QSpinBox::}{value}           \o \l{QSpinBox::}{valueChanged()}
    \endtable

    \sa QWizardPage::registerField()
*/
void QWizard::setDefaultProperty(const char *className, const char *property,
                                 const char *changedSignal)
{
    Q_D(QWizard);
    for (int i = d->defaultPropertyTable.count() - 1; i >= 0; --i) {
        if (qstrcmp(d->defaultPropertyTable.at(i).className, className) == 0) {
            d->defaultPropertyTable.remove(i);
            break;
        }
    }
    d->defaultPropertyTable.append(QWizardDefaultProperty(className, property, changedSignal));
}

/*!
    \reimp
*/
void QWizard::setVisible(bool visible)
{
    Q_D(QWizard);
    if (visible) {
        if (d->current == -1)
            restart();
    }
    QDialog::setVisible(visible);
}

/*!
    \reimp
*/
QSize QWizard::sizeHint() const
{
    Q_D(const QWizard);
    QSize result = d->mainLayout->totalSizeHint();
#ifdef Q_WS_S60
    QSize extra(QApplication::desktop()->availableGeometry(QCursor::pos()).size());
#else
    QSize extra(500, 360);
#endif
    if (d->wizStyle == MacStyle && d->current != -1) {
        QSize pixmap(currentPage()->pixmap(BackgroundPixmap).size());
        extra.setWidth(616);
        if (!pixmap.isNull()) {
            extra.setHeight(pixmap.height());

            /*
                The width isn't always reliable as a size hint, as
                some wizard backgrounds just cover the leftmost area.
                Use a rule of thumb to determine if the width is
                reliable or not.
            */
            if (pixmap.width() >= pixmap.height())
                extra.setWidth(pixmap.width());
        }
    }
    return result.expandedTo(extra);
}

/*!
    \fn void QWizard::currentIdChanged(int id)

    This signal is emitted when the current page changes, with the new
    current \a id.

    \sa currentId(), currentPage()
*/

/*!
    \fn void QWizard::helpRequested()

    This signal is emitted when the user clicks the \gui Help button.

    By default, no \gui Help button is shown. Call
    setOption(HaveHelpButton, true) to have one.

    Example:

    \snippet examples/dialogs/licensewizard/licensewizard.cpp 0
    \dots
    \snippet examples/dialogs/licensewizard/licensewizard.cpp 5
    \snippet examples/dialogs/licensewizard/licensewizard.cpp 7
    \dots
    \snippet examples/dialogs/licensewizard/licensewizard.cpp 8
    \codeline
    \snippet examples/dialogs/licensewizard/licensewizard.cpp 10
    \dots
    \snippet examples/dialogs/licensewizard/licensewizard.cpp 12
    \codeline
    \snippet examples/dialogs/licensewizard/licensewizard.cpp 14
    \codeline
    \snippet examples/dialogs/licensewizard/licensewizard.cpp 15

    \sa customButtonClicked()
*/

/*!
    \fn void QWizard::customButtonClicked(int which)

    This signal is emitted when the user clicks a custom button. \a
    which can be CustomButton1, CustomButton2, or CustomButton3.

    By default, no custom button is shown. Call setOption() with
    HaveCustomButton1, HaveCustomButton2, or HaveCustomButton3 to have
    one, and use setButtonText() or setButton() to configure it.

    \sa helpRequested()
*/

/*!
    Goes back to the previous page.

    This is equivalent to pressing the \gui Back button.

    \sa next(), accept(), reject(), restart()
*/
void QWizard::back()
{
    Q_D(QWizard);
    int n = d->history.count() - 2;
    if (n < 0)
        return;
    d->switchToPage(d->history.at(n), QWizardPrivate::Backward);
}

/*!
    Advances to the next page.

    This is equivalent to pressing the \gui Next or \gui Commit button.

    \sa nextId(), back(), accept(), reject(), restart()
*/
void QWizard::next()
{
    Q_D(QWizard);

    if (d->current == -1)
        return;

    if (validateCurrentPage()) {
        int next = nextId();
        if (next != -1) {
            if (d->history.contains(next)) {
                qWarning("QWizard::next: Page %d already met", next);
                return;
            }
            if (!d->pageMap.contains(next)) {
                qWarning("QWizard::next: No such page %d", next);
                return;
            }
            d->switchToPage(next, QWizardPrivate::Forward);
        }
    }
}

/*!
    Restarts the wizard at the start page. This function is called automatically when the
    wizard is shown.

    \sa startId()
*/
void QWizard::restart()
{
    Q_D(QWizard);
    d->disableUpdates();
    d->reset();
    d->switchToPage(startId(), QWizardPrivate::Forward);
    d->enableUpdates();
}

/*!
    \reimp
*/
bool QWizard::event(QEvent *event)
{
    Q_D(QWizard);
    if (event->type() == QEvent::StyleChange) { // Propagate style
        d->setStyle(style());
        d->updateLayout();
    }
#if !defined(QT_NO_STYLE_WINDOWSVISTA)
    else if (event->type() == QEvent::Show && d->vistaInitPending) {
        d->vistaInitPending = false;
        d->wizStyle = AeroStyle;
        d->handleAeroStyleChange();
    }
    else if (d->isVistaThemeEnabled()) {
        d->vistaHelper->mouseEvent(event);
    }
#endif
    return QDialog::event(event);
}

/*!
    \reimp
*/
void QWizard::resizeEvent(QResizeEvent *event)
{
    Q_D(QWizard);
    int heightOffset = 0;
#if !defined(QT_NO_STYLE_WINDOWSVISTA)
    if (d->isVistaThemeEnabled()) {
        heightOffset = d->vistaHelper->topOffset();
        if (d->isVistaThemeEnabled(QVistaHelper::VistaAero))
            heightOffset += d->vistaHelper->titleBarSize();
    }
#endif
    d->antiFlickerWidget->resize(event->size().width(), event->size().height() - heightOffset);
#if !defined(QT_NO_STYLE_WINDOWSVISTA)
    if (d->isVistaThemeEnabled())
        d->vistaHelper->resizeEvent(event);
#endif
    QDialog::resizeEvent(event);
}

/*!
    \reimp
*/
void QWizard::paintEvent(QPaintEvent * event)
{
    Q_D(QWizard);
    if (d->wizStyle == MacStyle && currentPage()) {
        QPixmap backgroundPixmap = currentPage()->pixmap(BackgroundPixmap);
        if (backgroundPixmap.isNull())
            return;

        QPainter painter(this);
        painter.drawPixmap(0, (height() - backgroundPixmap.height()) / 2, backgroundPixmap);
    }
#if !defined(QT_NO_STYLE_WINDOWSVISTA)
    else if (d->isVistaThemeEnabled()) {
        if (d->isVistaThemeEnabled(QVistaHelper::VistaBasic)) {
            QPainter painter(this);
            QColor color = d->vistaHelper->basicWindowFrameColor();
            painter.fillRect(0, 0, width(), QVistaHelper::topOffset(), color);
        }
        d->vistaHelper->paintEvent(event);
    }
#else
    Q_UNUSED(event);
#endif
}

#if defined(Q_WS_WIN)
/*!
    \reimp
*/
bool QWizard::winEvent(MSG *message, long *result)
{
#if !defined(QT_NO_STYLE_WINDOWSVISTA)
    Q_D(QWizard);
    if (d->isVistaThemeEnabled()) {
        const bool winEventResult = d->vistaHelper->handleWinEvent(message, result);
        if (QVistaHelper::vistaState() != d->vistaState) {
            d->vistaState = QVistaHelper::vistaState();
            d->vistaStateChanged = true;
            setWizardStyle(AeroStyle);
        }
        return winEventResult;
    } else {
        return QDialog::winEvent(message, result);
    }
#else
    return QDialog::winEvent(message, result);
#endif
}
#endif

/*!
    \reimp
*/
void QWizard::done(int result)
{
    Q_D(QWizard);
    // canceling leaves the wizard in a known state
    if (result == Rejected) {
        d->reset();
    } else {
        if (!validateCurrentPage())
            return;
    }
    QDialog::done(result);
}

/*!
    \fn void QWizard::initializePage(int id)

    This virtual function is called by QWizard to prepare page \a id
    just before it is shown either as a result of QWizard::restart()
    being called, or as a result of the user clicking \gui Next. (However, if the \l
    QWizard::IndependentPages option is set, this function is only
    called the first time the page is shown.)

    By reimplementing this function, you can ensure that the page's
    fields are properly initialized based on fields from previous
    pages.

    The default implementation calls QWizardPage::initializePage() on
    page(\a id).

    \sa QWizardPage::initializePage(), cleanupPage()
*/
void QWizard::initializePage(int theid)
{
    QWizardPage *page = this->page(theid);
    if (page)
        page->initializePage();
}

/*!
    \fn void QWizard::cleanupPage(int id)

    This virtual function is called by QWizard to clean up page \a id just before the
    user leaves it by clicking \gui Back (unless the \l QWizard::IndependentPages option is set).

    The default implementation calls QWizardPage::cleanupPage() on
    page(\a id).

    \sa QWizardPage::cleanupPage(), initializePage()
*/
void QWizard::cleanupPage(int theid)
{
    QWizardPage *page = this->page(theid);
    if (page)
        page->cleanupPage();
}

/*!
    This virtual function is called by QWizard when the user clicks
    \gui Next or \gui Finish to perform some last-minute validation.
    If it returns true, the next page is shown (or the wizard
    finishes); otherwise, the current page stays up.

    The default implementation calls QWizardPage::validatePage() on
    the currentPage().

    When possible, it is usually better style to disable the \gui
    Next or \gui Finish button (by specifying \l{mandatory fields} or
    by reimplementing QWizardPage::isComplete()) than to reimplement
    validateCurrentPage().

    \sa QWizardPage::validatePage(), currentPage()
*/
bool QWizard::validateCurrentPage()
{
    QWizardPage *page = currentPage();
    if (!page)
        return true;

    return page->validatePage();
}

/*!
    This virtual function is called by QWizard to find out which page
    to show when the user clicks the \gui Next button.

    The return value is the ID of the next page, or -1 if no page follows.

    The default implementation calls QWizardPage::nextId() on the
    currentPage().

    By reimplementing this function, you can specify a dynamic page
    order.

    \sa QWizardPage::nextId(), currentPage()
*/
int QWizard::nextId() const
{
    const QWizardPage *page = currentPage();
    if (!page)
        return -1;

    return page->nextId();
}

/*!
    \class QWizardPage
    \since 4.3
    \brief The QWizardPage class is the base class for wizard pages.

    QWizard represents a wizard. Each page is a QWizardPage. When
    you create your own wizards, you can use QWizardPage directly,
    or you can subclass it for more control.

    A page has the following attributes, which are rendered by
    QWizard: a \l title, a \l subTitle, and a \l{setPixmap()}{set of
    pixmaps}. See \l{Elements of a Wizard Page} for details. Once a
    page is added to the wizard (using QWizard::addPage() or
    QWizard::setPage()), wizard() returns a pointer to the
    associated QWizard object.

    Page provides five virtual functions that can be reimplemented to
    provide custom behavior:

    \list
    \o initializePage() is called to initialize the page's contents
       when the user clicks the wizard's \gui Next button. If you
       want to derive the page's default from what the user entered
       on previous pages, this is the function to reimplement.
    \o cleanupPage() is called to reset the page's contents when the
       user clicks the wizard's \gui Back button.
    \o validatePage() validates the page when the user clicks \gui
       Next or \gui Finish. It is often used to show an error message
       if the user has entered incomplete or invalid information.
    \o nextId() returns the ID of the next page. It is useful when
       \l{creating non-linear wizards}, which allow different
       traversal paths based on the information provided by the user.
    \o isComplete() is called to determine whether the \gui Next
       and/or \gui Finish button should be enabled or disabled. If
       you reimplement isComplete(), also make sure that
       completeChanged() is emitted whenever the complete state
       changes.
    \endlist

    Normally, the \gui Next button and the \gui Finish button of a
    wizard are mutually exclusive. If isFinalPage() returns true, \gui
    Finish is available; otherwise, \gui Next is available. By
    default, isFinalPage() is true only when nextId() returns -1. If
    you want to show \gui Next and \gui Final simultaneously for a
    page (letting the user perform an "early finish"), call
    setFinalPage(true) on that page. For wizards that support early
    finishes, you might also want to set the
    \l{QWizard::}{HaveNextButtonOnLastPage} and
    \l{QWizard::}{HaveFinishButtonOnEarlyPages} options on the
    wizard.

    In many wizards, the contents of a page may affect the default
    values of the fields of a later page. To make it easy to
    communicate between pages, QWizard supports a \l{Registering and
    Using Fields}{"field" mechanism} that allows you to register a
    field (e.g., a QLineEdit) on a page and to access its value from
    any page. Fields are global to the entire wizard and make it easy
    for any single page to access information stored by another page,
    without having to put all the logic in QWizard or having the
    pages know explicitly about each other. Fields are registered
    using registerField() and can be accessed at any time using
    field() and setField().

    \sa QWizard, {Class Wizard Example}, {License Wizard Example}
*/

/*!
    Constructs a wizard page with the given \a parent.

    When the page is inserted into a wizard using QWizard::addPage()
    or QWizard::setPage(), the parent is automatically set to be the
    wizard.

    \sa wizard()
*/
QWizardPage::QWizardPage(QWidget *parent)
    : QWidget(*new QWizardPagePrivate, parent, 0)
{
    connect(this, SIGNAL(completeChanged()), this, SLOT(_q_updateCachedCompleteState()));
}

/*!
    \property QWizardPage::title
    \brief the title of the page

    The title is shown by the QWizard, above the actual page. All
    pages should have a title.

    The title may be plain text or HTML, depending on the value of the
    \l{QWizard::titleFormat} property.

    By default, this property contains an empty string.

    \sa subTitle, {Elements of a Wizard Page}
*/
void QWizardPage::setTitle(const QString &title)
{
    Q_D(QWizardPage);
    d->title = title;
    if (d->wizard && d->wizard->currentPage() == this)
        d->wizard->d_func()->updateLayout();
}

QString QWizardPage::title() const
{
    Q_D(const QWizardPage);
    return d->title;
}

/*!
    \property QWizardPage::subTitle
    \brief the subtitle of the page

    The subtitle is shown by the QWizard, between the title and the
    actual page. Subtitles are optional. In
    \l{QWizard::ClassicStyle}{ClassicStyle} and
    \l{QWizard::ModernStyle}{ModernStyle}, using subtitles is
    necessary to make the header appear. In
    \l{QWizard::MacStyle}{MacStyle}, the subtitle is shown as a text
    label just above the actual page.

    The subtitle may be plain text or HTML, depending on the value of
    the \l{QWizard::subTitleFormat} property.

    By default, this property contains an empty string.

    \sa title, QWizard::IgnoreSubTitles, {Elements of a Wizard Page}
*/
void QWizardPage::setSubTitle(const QString &subTitle)
{
    Q_D(QWizardPage);
    d->subTitle = subTitle;
    if (d->wizard && d->wizard->currentPage() == this)
        d->wizard->d_func()->updateLayout();
}

QString QWizardPage::subTitle() const
{
    Q_D(const QWizardPage);
    return d->subTitle;
}

/*!
    Sets the pixmap for role \a which to \a pixmap.

    The pixmaps are used by QWizard when displaying a page. Which
    pixmaps are actually used depend on the \l{Wizard Look and
    Feel}{wizard style}.

    Pixmaps can also be set for the entire wizard using
    QWizard::setPixmap(), in which case they apply for all pages that
    don't specify a pixmap.

    \sa QWizard::setPixmap(), {Elements of a Wizard Page}
*/
void QWizardPage::setPixmap(QWizard::WizardPixmap which, const QPixmap &pixmap)
{
    Q_D(QWizardPage);
    Q_ASSERT(uint(which) < QWizard::NPixmaps);
    d->pixmaps[which] = pixmap;
    if (d->wizard && d->wizard->currentPage() == this)
        d->wizard->d_func()->updatePixmap(which);
}

/*!
    Returns the pixmap set for role \a which.

    Pixmaps can also be set for the entire wizard using
    QWizard::setPixmap(), in which case they apply for all pages that
    don't specify a pixmap.

    \sa QWizard::pixmap(), {Elements of a Wizard Page}
*/
QPixmap QWizardPage::pixmap(QWizard::WizardPixmap which) const
{
    Q_D(const QWizardPage);
    Q_ASSERT(uint(which) < QWizard::NPixmaps);

    const QPixmap &pixmap = d->pixmaps[which];
    if (!pixmap.isNull())
        return pixmap;

    if (wizard())
        return wizard()->pixmap(which);

    return pixmap;
}

/*!
    This virtual function is called by QWizard::initializePage() to
    prepare the page just before it is shown either as a result of QWizard::restart()
    being called, or as a result of the user clicking \gui Next.
    (However, if the \l QWizard::IndependentPages option is set, this function is only
    called the first time the page is shown.)

    By reimplementing this function, you can ensure that the page's
    fields are properly initialized based on fields from previous
    pages. For example:

    \snippet examples/dialogs/classwizard/classwizard.cpp 17

    The default implementation does nothing.

    \sa QWizard::initializePage(), cleanupPage(), QWizard::IndependentPages
*/
void QWizardPage::initializePage()
{
}

/*!
    This virtual function is called by QWizard::cleanupPage() when
    the user leaves the page by clicking \gui Back (unless the \l QWizard::IndependentPages
    option is set).

    The default implementation resets the page's fields to their
    original values (the values they had before initializePage() was
    called).

    \sa QWizard::cleanupPage(), initializePage(), QWizard::IndependentPages
*/
void QWizardPage::cleanupPage()
{
    Q_D(QWizardPage);
    if (d->wizard) {
        QVector<QWizardField> &fields = d->wizard->d_func()->fields;
        for (int i = 0; i < fields.count(); ++i) {
            const QWizardField &field = fields.at(i);
            if (field.page == this)
                field.object->setProperty(field.property, field.initialValue);
        }
    }
}

/*!
    This virtual function is called by QWizard::validateCurrentPage()
    when the user clicks \gui Next or \gui Finish to perform some
    last-minute validation. If it returns true, the next page is shown
    (or the wizard finishes); otherwise, the current page stays up.

    The default implementation returns true.

    When possible, it is usually better style to disable the \gui
    Next or \gui Finish button (by specifying \l{mandatory fields} or
    reimplementing isComplete()) than to reimplement validatePage().

    \sa QWizard::validateCurrentPage(), isComplete()
*/
bool QWizardPage::validatePage()
{
    return true;
}

/*!
    This virtual function is called by QWizard to determine whether
    the \gui Next or \gui Finish button should be enabled or
    disabled.

    The default implementation returns true if all \l{mandatory
    fields} are filled; otherwise, it returns false.

    If you reimplement this function, make sure to emit completeChanged(),
    from the rest of your implementation, whenever the value of isComplete()
    changes. This ensures that QWizard updates the enabled or disabled state of
    its buttons. An example of the reimplementation is
    available \l{http://qt.nokia.com/doc/qq/qq22-qwizard.html#validatebeforeitstoolate}
    {here}.

    \sa completeChanged(), isFinalPage()
*/
bool QWizardPage::isComplete() const
{
    Q_D(const QWizardPage);

    if (!d->wizard)
        return true;

    const QVector<QWizardField> &wizardFields = d->wizard->d_func()->fields;
    for (int i = wizardFields.count() - 1; i >= 0; --i) {
        const QWizardField &field = wizardFields.at(i);
        if (field.page == this && field.mandatory) {
            QVariant value = field.object->property(field.property);
            if (value == field.initialValue)
                return false;

#ifndef QT_NO_LINEEDIT
            if (QLineEdit *lineEdit = qobject_cast<QLineEdit *>(field.object)) {
                if (!lineEdit->hasAcceptableInput())
                    return false;
            }
#endif
#ifndef QT_NO_SPINBOX
            if (QAbstractSpinBox *spinBox = qobject_cast<QAbstractSpinBox *>(field.object)) {
                if (!spinBox->hasAcceptableInput())
                    return false;
            }
#endif
        }
    }
    return true;
}

/*!
    Explicitly sets this page to be final if \a finalPage is true.

    After calling setFinalPage(true), isFinalPage() returns true and the \gui
    Finish button is visible (and enabled if isComplete() returns
    true).

    After calling setFinalPage(false), isFinalPage() returns true if
    nextId() returns -1; otherwise, it returns false.

    \sa isComplete(), QWizard::HaveFinishButtonOnEarlyPages
*/
void QWizardPage::setFinalPage(bool finalPage)
{
    Q_D(QWizardPage);
    d->explicitlyFinal = finalPage;
    QWizard *wizard = this->wizard();
    if (wizard && wizard->currentPage() == this)
        wizard->d_func()->updateCurrentPage();
}

/*!
    This function is called by QWizard to determine whether the \gui
    Finish button should be shown for this page or not.

    By default, it returns true if there is no next page
    (i.e., nextId() returns -1); otherwise, it returns false.

    By explicitly calling setFinalPage(true), you can let the user perform an
    "early finish".

    \sa isComplete(), QWizard::HaveFinishButtonOnEarlyPages
*/
bool QWizardPage::isFinalPage() const
{
    Q_D(const QWizardPage);
    if (d->explicitlyFinal)
        return true;

    QWizard *wizard = this->wizard();
    if (wizard && wizard->currentPage() == this) {
        // try to use the QWizard implementation if possible
        return wizard->nextId() == -1;
    } else {
        return nextId() == -1;
    }
}

/*!
    Sets this page to be a commit page if \a commitPage is true; otherwise,
    sets it to be a normal page.

    A commit page is a page that represents an action which cannot be undone
    by clicking \gui Back or \gui Cancel.

    A \gui Commit button replaces the \gui Next button on a commit page. Clicking this
    button simply calls QWizard::next() just like clicking \gui Next does.

    A page entered directly from a commit page has its \gui Back button disabled.

    \sa isCommitPage()
*/
void QWizardPage::setCommitPage(bool commitPage)
{
    Q_D(QWizardPage);
    d->commit = commitPage;
    QWizard *wizard = this->wizard();
    if (wizard && wizard->currentPage() == this)
        wizard->d_func()->updateCurrentPage();
}

/*!
    Returns true if this page is a commit page; otherwise returns false.

    \sa setCommitPage()
*/
bool QWizardPage::isCommitPage() const
{
    Q_D(const QWizardPage);
    return d->commit;
}

/*!
    Sets the text on button \a which to be \a text on this page.

    By default, the text on buttons depends on the QWizard::wizardStyle,
    but may be redefined for the wizard as a whole using QWizard::setButtonText().

    \sa buttonText(), QWizard::setButtonText(), QWizard::buttonText()
*/
void QWizardPage::setButtonText(QWizard::WizardButton which, const QString &text)
{
    Q_D(QWizardPage);
    d->buttonCustomTexts.insert(which, text);
    if (wizard() && wizard()->currentPage() == this && wizard()->d_func()->btns[which])
        wizard()->d_func()->btns[which]->setText(text);
}

/*!
    Returns the text on button \a which on this page.

    If a text has ben set using setButtonText(), this text is returned.
    Otherwise, if a text has been set using QWizard::setButtonText(),
    this text is returned.

    By default, the text on buttons depends on the QWizard::wizardStyle.
    For example, on Mac OS X, the \gui Next button is called \gui
    Continue.

    \sa setButtonText(), QWizard::buttonText(), QWizard::setButtonText()
*/
QString QWizardPage::buttonText(QWizard::WizardButton which) const
{
    Q_D(const QWizardPage);

    if (d->buttonCustomTexts.contains(which))
        return d->buttonCustomTexts.value(which);

    if (wizard())
        return wizard()->buttonText(which);

    return QString();
}

/*!
    This virtual function is called by QWizard::nextId() to find
    out which page to show when the user clicks the \gui Next button.

    The return value is the ID of the next page, or -1 if no page follows.

    By default, this function returns the lowest ID greater than the ID
    of the current page, or -1 if there is no such ID.

    By reimplementing this function, you can specify a dynamic page
    order. For example:

    \snippet examples/dialogs/licensewizard/licensewizard.cpp 18

    \sa QWizard::nextId()
*/
int QWizardPage::nextId() const
{
    Q_D(const QWizardPage);

    if (!d->wizard)
        return -1;

    bool foundCurrentPage = false;

    const QWizardPrivate::PageMap &pageMap = d->wizard->d_func()->pageMap;
    QWizardPrivate::PageMap::const_iterator i = pageMap.constBegin();
    QWizardPrivate::PageMap::const_iterator end = pageMap.constEnd();

    for (; i != end; ++i) {
        if (i.value() == this) {
            foundCurrentPage = true;
        } else if (foundCurrentPage) {
            return i.key();
        }
    }
    return -1;
}

/*!
    \fn void QWizardPage::completeChanged()

    This signal is emitted whenever the complete state of the page
    (i.e., the value of isComplete()) changes.

    If you reimplement isComplete(), make sure to emit
    completeChanged() whenever the value of isComplete() changes, to
    ensure that QWizard updates the enabled or disabled state of its
    buttons.

    \sa isComplete()
*/

/*!
    Sets the value of the field called \a name to \a value.

    This function can be used to set fields on any page of the wizard.
    It is equivalent to calling
    wizard()->\l{QWizard::setField()}{setField(\a name, \a value)}.

    \sa QWizard::setField(), field(), registerField()
*/
void QWizardPage::setField(const QString &name, const QVariant &value)
{
    Q_D(QWizardPage);
    if (!d->wizard)
        return;
    d->wizard->setField(name, value);
}

/*!
    Returns the value of the field called \a name.

    This function can be used to access fields on any page of the
    wizard. It is equivalent to calling
    wizard()->\l{QWizard::field()}{field(\a name)}.

    Example:

    \snippet examples/dialogs/classwizard/classwizard.cpp 17

    \sa QWizard::field(), setField(), registerField()
*/
QVariant QWizardPage::field(const QString &name) const
{
    Q_D(const QWizardPage);
    if (!d->wizard)
        return QVariant();
    return d->wizard->field(name);
}

/*!
    Creates a field called \a name associated with the given \a
    property of the given \a widget. From then on, that property
    becomes accessible using field() and setField().

    Fields are global to the entire wizard and make it easy for any
    single page to access information stored by another page, without
    having to put all the logic in QWizard or having the pages know
    explicitly about each other.

    If \a name ends with an asterisk (\c *), the field is a mandatory
    field. When a page has mandatory fields, the \gui Next and/or
    \gui Finish buttons are enabled only when all mandatory fields
    are filled. This requires a \a changedSignal to be specified, to
    tell QWizard to recheck the value stored by the mandatory field.

    QWizard knows the most common Qt widgets. For these (or their
    subclasses), you don't need to specify a \a property or a \a
    changedSignal. The table below lists these widgets:

    \table
    \header \o Widget          \o Property                            \o Change Notification Signal
    \row    \o QAbstractButton \o bool \l{QAbstractButton::}{checked} \o \l{QAbstractButton::}{toggled()}
    \row    \o QAbstractSlider \o int \l{QAbstractSlider::}{value}    \o \l{QAbstractSlider::}{valueChanged()}
    \row    \o QComboBox       \o int \l{QComboBox::}{currentIndex}   \o \l{QComboBox::}{currentIndexChanged()}
    \row    \o QDateTimeEdit   \o QDateTime \l{QDateTimeEdit::}{dateTime} \o \l{QDateTimeEdit::}{dateTimeChanged()}
    \row    \o QLineEdit       \o QString \l{QLineEdit::}{text}       \o \l{QLineEdit::}{textChanged()}
    \row    \o QListWidget     \o int \l{QListWidget::}{currentRow}   \o \l{QListWidget::}{currentRowChanged()}
    \row    \o QSpinBox        \o int \l{QSpinBox::}{value}           \o \l{QSpinBox::}{valueChanged()}
    \endtable

    You can use QWizard::setDefaultProperty() to add entries to this
    table or to override existing entries.

    To consider a field "filled", QWizard simply checks that their
    current value doesn't equal their original value (the value they
    had before initializePage() was called). For QLineEdit, it also
    checks that
    \l{QLineEdit::hasAcceptableInput()}{hasAcceptableInput()} returns
    true, to honor any validator or mask.

    QWizard's mandatory field mechanism is provided for convenience.
    It can be bypassed by reimplementing QWizardPage::isComplete().

    \sa field(), setField(), QWizard::setDefaultProperty()
*/
void QWizardPage::registerField(const QString &name, QWidget *widget, const char *property,
                                const char *changedSignal)
{
    Q_D(QWizardPage);
    QWizardField field(this, name, widget, property, changedSignal);
    if (d->wizard) {
        d->wizard->d_func()->addField(field);
    } else {
        d->pendingFields += field;
    }
}

/*!
    Returns the wizard associated with this page, or 0 if this page
    hasn't been inserted into a QWizard yet.

    \sa QWizard::addPage(), QWizard::setPage()
*/
QWizard *QWizardPage::wizard() const
{
    Q_D(const QWizardPage);
    return d->wizard;
}

QT_END_NAMESPACE

#include "moc_qwizard.cpp"

#endif // QT_NO_WIZARD